// digesttools are utility functions for answering questions about digests.
package digesttools

import (
	"context"
	"math"

	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/golden/go/diff"
	"go.skia.org/infra/golden/go/digest_counter"
	"go.skia.org/infra/golden/go/expectations"
	"go.skia.org/infra/golden/go/types"
)

// ClosestDiffFinder is able to query a diffstore for digests
// that are the closest negative or closest positive to
// a given digest. Implementations should be considered
// not-thread-safe.
type ClosestDiffFinder interface {
	// Precompute allows the implementation to warm any caches.
	// Call before doing a batch of ClosestDigest calls.
	Precompute(ctx context.Context) error

	// ClosestDigest returns the closest digest of type 'label' to 'digest',
	// or NoDigestFound if there aren't any positive digests.
	//
	// If no digest of type 'label' is found then Closest.Digest is the empty string.
	ClosestDigest(ctx context.Context, test types.TestName, digest types.Digest, label expectations.Label) (*Closest, error)
}

// Closest describes one digest that is the closest another digest.
type Closest struct {
	// The closest digest, empty if there are no digests to compare to.
	Digest     types.Digest `json:"digest"`
	Diff       float32      `json:"diff"`       // A percent value.
	DiffPixels float32      `json:"diffPixels"` // A percent value.
	MaxRGBA    [4]int       `json:"maxRGBA"`
}

const NoDigestFound = types.Digest("")

// newClosest returns an initialized Closest struct, defaulting to
// NoDigestFound and related values.
func newClosest() *Closest {
	return &Closest{
		Digest:     NoDigestFound,
		Diff:       math.MaxFloat32,
		DiffPixels: math.MaxFloat32,
		MaxRGBA:    [4]int{},
	}
}

// Impl implements the ClosestDiffFinder interface
type Impl struct {
	expectations expectations.ReadOnly
	dCounter     digest_counter.DigestCounter
	diffStore    diff.DiffStore

	cachedUnavailableDigests map[types.Digest]*diff.DigestFailure
}

// NewClosestDiffFinder returns a *Impl loaded with the given data sources.
func NewClosestDiffFinder(exp expectations.ReadOnly, dCounter digest_counter.DigestCounter, diffStore diff.DiffStore) *Impl {
	return &Impl{
		expectations: exp,
		dCounter:     dCounter,
		diffStore:    diffStore,
	}
}

// Precompute implements the ClosestDiffFinder interface.
func (i *Impl) Precompute(ctx context.Context) error {
	var err error
	i.cachedUnavailableDigests, err = i.diffStore.UnavailableDigests(ctx)
	return skerr.Wrap(err)
}

// ClosestDigest implements the ClosestDiffFinder interface.
func (i *Impl) ClosestDigest(ctx context.Context, test types.TestName, digest types.Digest, label expectations.Label) (*Closest, error) {
	ret := newClosest()

	if _, ok := i.cachedUnavailableDigests[digest]; ok {
		return ret, nil
	}

	// Locate all digests that this test produces and match the given label.
	selected := types.DigestSlice{}
	testDigests := i.dCounter.ByTest()[test]
	for d := range testDigests {
		if _, ok := i.cachedUnavailableDigests[d]; !ok && (i.expectations.Classification(test, d) == label) {
			selected = append(selected, d)
		}
	}

	if len(selected) == 0 {
		return ret, nil
	}

	if diffMetrics, err := i.diffStore.Get(ctx, digest, selected); err != nil {
		return nil, skerr.Wrapf(err, "getting diffs for %s and %d comparisons", digest, len(selected))
	} else {
		for digest, dm := range diffMetrics {
			if delta := diff.CombinedDiffMetric(dm, nil, nil); delta < ret.Diff {
				ret.Digest = digest
				ret.Diff = delta
				ret.DiffPixels = dm.PixelDiffPercent
				ret.MaxRGBA = dm.MaxRGBADiffs
			}
		}
		return ret, nil
	}
}

// Make sure Impl fulfills the ClosestDiffFinder interface
var _ ClosestDiffFinder = (*Impl)(nil)
