package dynamicdiff

import (
	"fmt"
	"image"
	"path/filepath"
	"strings"

	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/golden/go/diff"
	"go.skia.org/infra/golden/go/diffstore"
)

type DynamicDiffMetrics struct {
	// NumDiffPixels is the number of static pixels that are different.
	NumDiffPixels int `json:"numDiffPixels"`

	// PixelDiffPercent is the percentage of static pixels that are different.
	PixelDiffPercent float32 `json:"pixelDiffPercent"`

	// MaxRGBDiffs contains the maximum difference of each channel.
	MaxRGBDiffs []int `json:"maxRGBDiffs"`

	// NumStaticPixels is the total number of static pixels.
	NumStaticPixels int `json:"numStaticPixels"`

	// NumDynamicPixels is the total number of dynamic pixels. Note that
	// NumStaticPixels + NumDynamicPixels = number of total pixels.
	NumDynamicPixels int `json:"numDynamicPixels"`
}

// PixelDiffStoreMapper implements the diffstore.DiffStoreMapper interface.
// It uses instances of
// of an imageID is: runID/{nopatch/withpatch}/rank/URLfilename. A runID has the
// format userID-timeStamp.
type PixelDiffStoreMapper struct {
	util.LRUCodec
}

// NewPixelDiffStoreMapper returns a new instance of PixelDiffStoreMapper with
// a codec that encodes/decodes instance of DynamicDiffMetrics to/from JSON.
func NewPixelDiffStoreMapper(diffInstance interface{}) diffstore.DiffStoreMapper {
	return PixelDiffStoreMapper{LRUCodec: util.JSONCodec(&DynamicDiffMetrics{})}
}

// DiffFn implements the diffstore.DiffStoreMapper interface.
func (g PixelDiffStoreMapper) DiffFn(leftImg *image.NRGBA, rightImg *image.NRGBA) (interface{}, *image.NRGBA) {
	return DynamicContentDiff(leftImg, rightImg)
}

// DiffID implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) DiffID(leftImgID, rightImgID string) string {
	// Return a string containing the common runID, rank and URL of the two image paths.
	path := strings.Split(leftImgID, "/")
	return strings.Join([]string{path[0], path[2], path[3]}, ":")
}

// SplitDiffID implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) SplitDiffID(diffID string) (string, string) {
	path := strings.Split(diffID, ":")
	return filepath.Join(path[0], "nopatch", path[1], path[2]),
		filepath.Join(path[0], "withpatch", path[1], path[2])
}

// DiffPath implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) DiffPath(leftImgID, rightImgID string) string {
	path := strings.Split(leftImgID, "/")
	imageName := path[0] + "/" + path[3]
	return fmt.Sprintf("%s.%s", imageName, diffstore.IMG_EXTENSION)
}

// ImagePaths implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) ImagePaths(imageID string) (string, string, string) {
	localPath := fmt.Sprintf("%s.%s", imageID, diffstore.IMG_EXTENSION)
	path := strings.Split(imageID, "/")
	runID := strings.Split(path[0], "-")
	timeStamp := runID[1]
	datePath := filepath.Join(timeStamp[0:4], timeStamp[4:6], timeStamp[6:8], timeStamp[8:10])
	gsPath := filepath.Join(datePath, localPath)
	return localPath, "", gsPath
}

// IsValidDiffImgID implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) IsValidDiffImgID(diffImgID string) bool {
	path := strings.Split(diffImgID, "/")
	return len(path) == 2
}

// IsValidImgID implements the diffstore.DiffStoreMapper interface.
func (p PixelDiffStoreMapper) IsValidImgID(imgID string) bool {
	path := strings.Split(imgID, "/")
	return len(path) == 4
}

// DynamicContentDiff is a function that calculates the DiffMetrics and diff
// image for the provided images, taking into account that pixels with dynamic
// content are marked cyan and removing such pixels from the calculations. The
// images are assumed to have the same dimensions.
func DynamicContentDiff(left, right *image.NRGBA) (*DynamicDiffMetrics, *image.NRGBA) {
	bounds := left.Bounds()
	resultImg := image.NewNRGBA(image.Rect(0, 0, bounds.Dx(), bounds.Dy()))

	// Pix is a []uint8 of R, G, B, A, R, G, B, A, ... values.
	p1 := left.Pix
	p2 := right.Pix

	numStaticPixels := 0
	numDynamicPixels := 0
	numDiffPixels := 0
	maxRGBDiffs := make([]int, 3)

	// Each pixel consists of 4 values (R, G, B, A). Alpha is ignored for diff
	// purposes.
	for i := 0; i < len(p1); i += 4 {
		r, g, b := p1[i+0], p1[i+1], p1[i+2]
		R, G, B := p2[i+0], p2[i+1], p2[i+2]

		// Ignore pixels with dynamic content, mark the pixel in the diff image as
		// dynamic, and increment the count of dynamic pixels.
		if isDynamicContentPixel(r, g, b) || isDynamicContentPixel(R, G, B) {
			copy(resultImg.Pix[i:], []uint8{0, 255, 255, 255})
			numDynamicPixels++
			continue
		}

		// Increment the count of static pixels.
		numStaticPixels++

		// If the pixels do not have the same RGB values, update the diff metrics
		// and the diff image.
		if r != R || g != G || b != B {
			numDiffPixels++
			dr := util.AbsInt(int(r) - int(R))
			dg := util.AbsInt(int(g) - int(G))
			db := util.AbsInt(int(b) - int(B))
			maxRGBDiffs[0] = util.MaxInt(dr, maxRGBDiffs[0])
			maxRGBDiffs[1] = util.MaxInt(dg, maxRGBDiffs[1])
			maxRGBDiffs[2] = util.MaxInt(db, maxRGBDiffs[2])
			copy(resultImg.Pix[i:], diff.PixelDiffColor[deltaOffset(dr+dg+db)])
		}
	}

	return &DynamicDiffMetrics{
		NumDiffPixels:    numDiffPixels,
		PixelDiffPercent: diff.GetPixelDiffPercent(numDiffPixels, numStaticPixels),
		MaxRGBDiffs:      maxRGBDiffs,
		NumStaticPixels:  numStaticPixels,
		NumDynamicPixels: numDynamicPixels,
	}, resultImg
}

// If the pixel is cyan, it contains dynamic content. This reflects the current
// behavior of the CT screenshot benchmark when the dynamic content detection
// flag is enabled.
func isDynamicContentPixel(red, green, blue uint8) bool {
	return red == 0 && green == 255 && blue == 255
}

// If the pixels don't have the same value, the minimum value that can be passed
// to this function is 1 and the maximum is 255*3 = 765. We must convert the
// range [1, 765] to the range [1, 7] in order to select the correct offset
// into the diff.PixelDiffColor slice. To convert a number n from range [x, y]
// to [a, b], we use the following formula:
// 			  (b - a)(n - x)
// f(n) = -------------- + a
//						y - x
func deltaOffset(n int) int {
	ret := 6*(n-1)/764 + 1
	if ret < 1 || ret > 7 {
		sklog.Fatalf("Input out of range [1, 765]: %d", n)
	}
	return ret - 1
}
