// warmer makes sure we've pre-warmed the diffcache for normal queries.
// TODO(kjlubick): can this be merged into digesttools?
package warmer

import (
	"context"

	"go.skia.org/infra/go/metrics2"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/golden/go/digest_counter"
	"go.skia.org/infra/golden/go/digesttools"
	"go.skia.org/infra/golden/go/shared"
	"go.skia.org/infra/golden/go/summary"
	"go.skia.org/infra/golden/go/types"
	"go.skia.org/infra/golden/go/types/expectations"
)

// DiffWarmer pre-calculates diffs that will be requested by the front-end
// when showing diffs for a certain page.
type DiffWarmer interface {
	// PrecomputeDiffs goes through all untriaged digests and precomputes their
	// closest positive and closest negative digest. This will make sure diffstore
	// has those diffs pre-drawn and can serve them quickly to the frontend.
	// If testNames is not empty, only those the diffs for those names will be
	// precomputed.
	PrecomputeDiffs(ctx context.Context, summaries []*summary.TriageStatus, testNames types.TestNameSet, dCounter digest_counter.DigestCounter, diffFinder digesttools.ClosestDiffFinder) error
}

type WarmerImpl struct {
}

// New creates an new instance of WarmerImpl.
func New() *WarmerImpl {
	return &WarmerImpl{}
}

// PrecomputeDiffs implements the DiffWarmer interface
func (w *WarmerImpl) PrecomputeDiffs(ctx context.Context, summaries []*summary.TriageStatus, testNames types.TestNameSet, dCounter digest_counter.DigestCounter, diffFinder digesttools.ClosestDiffFinder) error {
	defer shared.NewMetricsTimer("warmer_loop").Stop()
	err := diffFinder.Precompute(ctx)
	if err != nil {
		return skerr.Wrapf(err, "preparing to compute diffs")
	}
	// We go through all the diffs to precompute. If there was a flake or something and we get an
	// error from the diffFinder, we keep going to try to warm as much as possible (unless our
	// context signals us to stop).
	var firstErr error
	errCount := 0
	for _, sum := range summaries {
		test := sum.Name
		if ctx.Err() != nil {
			sklog.Warningf("PrecomputeDiffs stopped by context error: %s", ctx.Err())
			break
		}
		if len(testNames) > 0 && !testNames[test] {
			// Skipping this test because it wasn't in the set of tests to precompute.
			continue
		}
		for _, digest := range sum.UntHashes {
			// Only pre-compute those diffs for the test_name+digest pair if it was observed
			t := dCounter.ByTest()[test]
			if t != nil {
				nt := metrics2.NewTimer("gold_warmer_cycle")
				// Calculating the closest digest has the side effect of filling
				// in the diffstore with the diff images.
				_, err := diffFinder.ClosestDigest(ctx, test, digest, expectations.Positive)
				if err != nil {
					if firstErr == nil {
						firstErr = err
					}
					sklog.Debugf("non-terminating error precomputing diff: %s", err)
					errCount++
				}
				_, err = diffFinder.ClosestDigest(ctx, test, digest, expectations.Negative)
				if err != nil {
					if firstErr == nil {
						firstErr = err
					}
					sklog.Debugf("non-terminating error precomputing diff: %s", err)
					errCount++
				}
				nt.Stop()
			}
		}
	}
	if errCount > 0 {
		return skerr.Wrapf(firstErr, "and %d other error(s) precomputing diffs", errCount-1)
	}
	return ctx.Err()
}

// Make sure WarmerImpl fulfills the DiffWarmer interface
var _ DiffWarmer = (*WarmerImpl)(nil)
