/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"log"
	"net/http"
	"os"
	"path"
	"sort"
	"strings"
	"sync"

	"go.skia.org/infra/golden/go/search"
)

const (
	min_png = "min.png"
	max_png = "max.png"
)

type ExportTestRecordArray []search.ExportTestRecord

func (a ExportTestRecordArray) Len() int           { return len(a) }
func (a ExportTestRecordArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ExportTestRecordArray) Less(i, j int) bool { return a[i].TestName < a[j].TestName }

func in(v string, a []string) bool {
	for _, u := range a {
		if u == v {
			return true
		}
	}
	return false
}

func clampU8(v int) uint8 {
	if v < 0 {
		return 0
	} else if v > 255 {
		return 255
	}
	return uint8(v)
}

func processTest(testName string, imgUrls []string, output string) (bool, error) {
	if strings.ContainsRune(testName, '/') {
		return false, nil
	}
	output_directory := path.Join(output, testName)
	var img_max image.NRGBA
	var img_min image.NRGBA
	for _, url := range imgUrls {
		resp, err := http.Get(url)
		if err != nil {
			return false, err
		}
		img, err := png.Decode(resp.Body)
		resp.Body.Close()
		if err != nil {
			return false, err
		}
		if img_max.Rect.Max.X == 0 {
			// N.B. img_max.Pix may alias img.Pix (if they're already NRGBA).
			img_max = toNrgba(img)
			img_min = copyNrgba(img_max)
			continue
		}
		w := img.Bounds().Max.X - img.Bounds().Min.X
		h := img.Bounds().Max.Y - img.Bounds().Min.Y
		if img_max.Rect.Max.X != w || img_max.Rect.Max.Y != h {
			return false, errors.New("size mismatch")
		}
		img_nrgba := toNrgba(img)
		for i, value := range img_nrgba.Pix {
			if value > img_max.Pix[i] {
				img_max.Pix[i] = value
			} else if value < img_min.Pix[i] {
				img_min.Pix[i] = value
			}
		}
	}
	if img_max.Rect.Max.X == 0 {
		return false, nil
	}

	if err := os.Mkdir(output_directory, os.ModePerm); err != nil && !os.IsExist(err) {
		return false, err
	}
	if err := writePngToFile(path.Join(output_directory, min_png), &img_min); err != nil {
		return false, err
	}
	if err := writePngToFile(path.Join(output_directory, max_png), &img_max); err != nil {
		return false, err
	}
	return true, nil
}

type LockedStringList struct {
	List []string
	mux sync.Mutex
}

func (l *LockedStringList) add(v string) {
	l.mux.Lock()
	defer l.mux.Unlock()
	l.List = append(l.List, v)
}


func readMetaJsonFile(filename string) ([]search.ExportTestRecord, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	dec := json.NewDecoder(file)
	var records []search.ExportTestRecord
	err = dec.Decode(&records)
	return records, err
}

func writePngToFile(path string, img image.Image) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return png.Encode(file, img)
}

// to_nrgb() may return a shallow copy of img if it's already NRGBA.
func toNrgba(img image.Image) image.NRGBA {
	switch v := img.(type) {
	case *image.NRGBA:
		return *v
	}
	nimg := *image.NewNRGBA(img.Bounds())
	draw.Draw(&nimg, img.Bounds(), img, image.Point{0, 0}, draw.Src)
	return nimg
}

func copyNrgba(src image.NRGBA) image.NRGBA {
	dst := image.NRGBA{make([]uint8, len(src.Pix)), src.Stride, src.Rect}
	copy(dst.Pix, src.Pix)
	return dst
}

func main() {
	if len(os.Args) != 3 {
		log.Printf("Usage:\n  %s INPUT.json OUTPUT_DIRECTORY\n\n", os.Args[0])
		os.Exit(1)
	}
	input := os.Args[1]
	output := os.Args[2]
	// output is removed and replaced with a clean directory.
	if err := os.RemoveAll(output); err != nil && !os.IsNotExist(err) {
		log.Fatal(err)
	}
	if err := os.MkdirAll(output, os.ModePerm); err != nil && !os.IsExist(err) {
		log.Fatal(err)
	}

	records, err := readMetaJsonFile(input)
	if err != nil {
		log.Fatal(err)
	}
	sort.Sort(ExportTestRecordArray(records))

	var results LockedStringList
	var wg sync.WaitGroup
	for _, record := range records {
		var goodUrls []string
		for _, digest := range record.Digests {
			if (in("vk", digest.ParamSet["config"]) ||
				in("gles", digest.ParamSet["config"])) &&
				digest.Status == "positive" {
				goodUrls = append(goodUrls, digest.URL)
			}
		}
		wg.Add(1)
		go func(testName string, imgUrls []string, output string, results* LockedStringList) {
			defer wg.Done()
			success, err := processTest(testName, imgUrls, output)
			if err != nil {
				log.Fatal(err)
			}
			if success {
				results.add(testName)
			}
			fmt.Printf("\r%-60s", testName)
		}(record.TestName, goodUrls, output, &results)
	}
	wg.Wait()
	fmt.Printf("\r%60s\n", "")
	sort.Strings(results.List)
	modelFile, err := os.Create(path.Join(output, "models.txt"))
	if err != nil {
		log.Fatal(err)
	}
	for _, v := range results.List {
		fmt.Fprintln(modelFile, v)
	}
}
