// Package ref_differ contains routines to calculate reference diffs for digests.
package ref_differ

import (
	"context"
	"math"
	"sort"

	"go.skia.org/infra/go/paramtools"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/go/diff"
	"go.skia.org/infra/golden/go/expectations"
	"go.skia.org/infra/golden/go/indexer"
	"go.skia.org/infra/golden/go/search/common"
	"go.skia.org/infra/golden/go/search/frontend"
	"go.skia.org/infra/golden/go/types"
)

// RefDiffer is an interface for calculating the ReferenceDiffs for a given test+digest pair.
// A 'diff' captures the difference between two digests.
// To deal with digests in a human friendly way we calculate reference
// diffs for each digest, most notably the closest negative and
// positive digest. But other reference diffs might make sense and
// should be added here.
type RefDiffer interface {
	// FillRefDiffs fills in d with the closest negative and positive images (digests) to it.
	// It uses "metric" to determine "closeness". If match is non-nil, it only returns those
	// digests that match d's params for the keys in match. If rhsQuery is not empty, it only
	// compares against digests that match rhsQuery.
	FillRefDiffs(ctx context.Context, d *frontend.SearchResult, metric string, match []string, rhsQuery paramtools.ParamSet, is types.IgnoreState) error
}

// DiffImpl aggregates the helper objects needed to calculate reference diffs.
type DiffImpl struct {
	exp       expectations.Classifier
	diffStore diff.DiffStore
	idx       indexer.IndexSearcher
}

// New returns a *DiffImpl using given types.
func New(exp expectations.Classifier, diffStore diff.DiffStore, idx indexer.IndexSearcher) *DiffImpl {
	return &DiffImpl{
		exp:       exp,
		diffStore: diffStore,
		idx:       idx,
	}
}

// FillRefDiffs implements the RefDiffer interface.
func (r *DiffImpl) FillRefDiffs(ctx context.Context, d *frontend.SearchResult, metric string, match []string, rhsQuery paramtools.ParamSet, iState types.IgnoreState) error {
	paramsByDigest := r.idx.GetParamsetSummaryByTest(iState)[d.Test]

	// TODO(kjlubick) maybe make this use an errgroup
	posDigests := r.getDigestsWithLabel(d, match, paramsByDigest, rhsQuery, expectations.Positive)
	negDigests := r.getDigestsWithLabel(d, match, paramsByDigest, rhsQuery, expectations.Negative)

	var err error
	ret := make(map[common.RefClosest]*frontend.SRDiffDigest, 2)
	ret[common.PositiveRef], err = r.getClosestDiff(ctx, metric, d.Digest, posDigests)
	if err != nil {
		return skerr.Wrapf(err, "fetching positive diffs")
	}
	ret[common.NegativeRef], err = r.getClosestDiff(ctx, metric, d.Digest, negDigests)
	if err != nil {
		return skerr.Wrapf(err, "fetching negative diffs")
	}

	// Find the minimum according to the diff metric.
	closest := common.NoRef
	minDiff := float32(math.Inf(1))
	dCount := r.idx.DigestCountsByTest(iState)[d.Test]
	for ref, srdd := range ret {
		if srdd != nil {
			// Fill in the missing fields.
			srdd.Status = r.exp.Classification(d.Test, srdd.Digest).String()
			srdd.ParamSet = paramsByDigest[srdd.Digest]
			srdd.OccurrencesInTile = dCount[srdd.Digest]

			// Find the minimum.
			if srdd.DiffMetrics.Diffs[metric] < minDiff {
				closest = ref
				minDiff = srdd.DiffMetrics.Diffs[metric]
			}
		}
	}
	d.ClosestRef = closest
	d.RefDiffs = ret
	return nil
}

// getDigestsWithLabel return all digests within the given test that
// have the given label assigned to them and where the parameters
// listed in 'match' match.
func (r *DiffImpl) getDigestsWithLabel(s *frontend.SearchResult, match []string, paramsByDigest map[types.Digest]paramtools.ParamSet, rhsQuery paramtools.ParamSet, targetLabel expectations.Label) types.DigestSlice {
	ret := types.DigestSlice{}
	for d, digestParams := range paramsByDigest {
		// Accept all digests that are:  in the set of allowed digests
		//                              match the target label and where the required
		//                              parameter fields match.
		if (len(rhsQuery) == 0 || rhsQuery.Matches(digestParams)) &&
			(r.exp.Classification(s.Test, d) == targetLabel) &&
			paramSetsMatch(match, s.ParamSet, digestParams) {
			ret = append(ret, d)
		}
	}
	// Sort for determinism
	sort.Sort(ret)
	return ret
}

// getClosestDiff returns the closest diff between a digest and a set of digest.
func (r *DiffImpl) getClosestDiff(ctx context.Context, metric string, digest types.Digest, compDigests types.DigestSlice) (*frontend.SRDiffDigest, error) {
	if len(compDigests) == 0 {
		return nil, nil
	}

	diffs, err := r.diffStore.Get(ctx, digest, compDigests)
	if err != nil {
		return nil, skerr.Wrapf(err, "diffing digest %s with %d other digests", digest, len(compDigests))
	}

	if len(diffs) == 0 {
		return nil, nil
	}

	minDiff := float32(math.Inf(1))
	minDigest := types.Digest("")
	for resultDigest, diffMetrics := range diffs {
		if diffMetrics.Diffs[metric] < minDiff {
			minDiff = diffMetrics.Diffs[metric]
			minDigest = resultDigest
		}
	}

	return &frontend.SRDiffDigest{
		DiffMetrics: diffs[minDigest],
		Digest:      minDigest,
	}, nil
}

// paramSetsMatch returns true if the two param sets have matching values for the parameters listed
// in 'match'. If one of them is nil or completely empty there is always a match.
func paramSetsMatch(match []string, p1, p2 paramtools.ParamSet) bool {
	if len(p1) == 0 || len(p2) == 0 {
		return true
	}

	for _, paramKey := range match {
		vals1, ok1 := p1[paramKey]
		vals2, ok2 := p2[paramKey]
		if !ok1 || !ok2 {
			return false
		}
		found := false
		for _, v := range vals1 {
			if util.In(v, vals2) {
				found = true
				break
			}
		}
		if !found {
			return false
		}
	}
	return true
}

// Make sure DiffImpl fulfills the RefDiffer interface.
var _ RefDiffer = (*DiffImpl)(nil)
