// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package iconvg

import (
	"bytes"
	"fmt"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// disassemble returns a disassembly of an encoded IconVG graphic. Users of
// this package aren't expected to want to do this, so it lives in a _test.go
// file, but it can be useful for debugging.
func disassemble(src []byte) ([]byte, error) {
	w := new(bytes.Buffer)
	p := func(b []byte, format string, args ...interface{}) {
		const hex = "0123456789abcdef"
		var buf [14]byte
		for i := range buf {
			buf[i] = ' '
		}
		for i, x := range b {
			buf[3*i+0] = hex[x>>4]
			buf[3*i+1] = hex[x&0x0f]
		}
		w.Write(buf[:])
		fmt.Fprintf(w, format, args...)
	}
	m := Metadata{}
	if err := decode(nil, p, &m, false, buffer(src), nil); err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

var (
	_ Destination = (*Encoder)(nil)
	_ Destination = (*Rasterizer)(nil)
)

func encodePNG(dstFilename string, src image.Image) error {
	f, err := os.Create(dstFilename)
	if err != nil {
		return err
	}
	encErr := png.Encode(f, src)
	closeErr := f.Close()
	if encErr != nil {
		return encErr
	}
	return closeErr
}

func decodePNG(srcFilename string) (image.Image, error) {
	f, err := os.Open(srcFilename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return png.Decode(f)
}

func checkApproxEqual(m0, m1 image.Image) error {
	diff := func(a, b uint32) uint32 {
		if a < b {
			return b - a
		}
		return a - b
	}

	bounds0 := m0.Bounds()
	bounds1 := m1.Bounds()
	if bounds0 != bounds1 {
		return fmt.Errorf("bounds differ: got %v, want %v", bounds0, bounds1)
	}
	for y := bounds0.Min.Y; y < bounds0.Max.Y; y++ {
		for x := bounds0.Min.X; x < bounds0.Max.X; x++ {
			r0, g0, b0, a0 := m0.At(x, y).RGBA()
			r1, g1, b1, a1 := m1.At(x, y).RGBA()

			// TODO: be more principled in picking this magic threshold, other
			// than what the difference is, in practice, in x/image/vector's
			// fixed and floating point rasterizer?
			const D = 0xffff * 12 / 100 // Diff threshold of 12%.

			if diff(r0, r1) > D || diff(g0, g1) > D || diff(b0, b1) > D || diff(a0, a1) > D {
				return fmt.Errorf("at (%d, %d):\n"+
					"got  RGBA %#04x, %#04x, %#04x, %#04x\n"+
					"want RGBA %#04x, %#04x, %#04x, %#04x",
					x, y, r0, g0, b0, a0, r1, g1, b1, a1)
			}
		}
	}
	return nil
}

func diffLines(t *testing.T, got, want string) {
	gotLines := strings.Split(got, "\n")
	wantLines := strings.Split(want, "\n")
	for i := 1; ; i++ {
		if len(gotLines) == 0 {
			t.Errorf("line %d:\ngot  %q\nwant %q", i, "", wantLines[0])
			return
		}
		if len(wantLines) == 0 {
			t.Errorf("line %d:\ngot  %q\nwant %q", i, gotLines[0], "")
			return
		}
		g, w := gotLines[0], wantLines[0]
		gotLines = gotLines[1:]
		wantLines = wantLines[1:]
		if g != w {
			t.Errorf("line %d:\ngot  %q\nwant %q", i, g, w)
			return
		}
	}
}

var testdataTestCases = []struct {
	filename string
	variants string
}{
	{"testdata/action-info.lores", ""},
	{"testdata/action-info.hires", ""},
	{"testdata/arcs", ""},
	{"testdata/blank", ""},
	{"testdata/cowbell", ""},
	{"testdata/elliptical", ""},
	{"testdata/favicon", ""},
	{"testdata/gradient", ""},
	{"testdata/lod-polygon", ";64"},
	{"testdata/video-005.primitive", ""},
}

func TestDisassembly(t *testing.T) {
	for _, tc := range testdataTestCases {
		ivgData, err := ioutil.ReadFile(filepath.FromSlash(tc.filename) + ".ivg")
		if err != nil {
			t.Errorf("%s: ReadFile: %v", tc.filename, err)
			continue
		}
		got, err := disassemble(ivgData)
		if err != nil {
			t.Errorf("%s: disassemble: %v", tc.filename, err)
			continue
		}
		wantFilename := filepath.FromSlash(tc.filename) + ".ivg.disassembly"
		if overwriteTestdataFiles {
			if err := ioutil.WriteFile(filepath.FromSlash(wantFilename), got, 0666); err != nil {
				t.Errorf("%s: WriteFile: %v", tc.filename, err)
			}
			continue
		}
		want, err := ioutil.ReadFile(wantFilename)
		if err != nil {
			t.Errorf("%s: ReadFile: %v", tc.filename, err)
			continue
		}
		if !bytes.Equal(got, want) {
			t.Errorf("%s: got:\n%s\nwant:\n%s", tc.filename, got, want)
			diffLines(t, string(got), string(want))
		}
	}
}

func TestRasterizer(t *testing.T) {
	for _, tc := range testdataTestCases {
		ivgData, err := ioutil.ReadFile(filepath.FromSlash(tc.filename) + ".ivg")
		if err != nil {
			t.Errorf("%s: ReadFile: %v", tc.filename, err)
			continue
		}
		md, err := DecodeMetadata(ivgData)
		if err != nil {
			t.Errorf("%s: DecodeMetadata: %v", tc.filename, err)
			continue
		}

		for _, variant := range strings.Split(tc.variants, ";") {
			length := 256
			if variant == "64" {
				length = 64
			}
			width, height := length, length
			if dx, dy := md.ViewBox.AspectRatio(); dx < dy {
				width = int(float32(length) * dx / dy)
			} else {
				height = int(float32(length) * dy / dx)
			}

			got := image.NewRGBA(image.Rect(0, 0, width, height))
			var z Rasterizer
			z.SetDstImage(got, got.Bounds(), draw.Src)
			if err := Decode(&z, ivgData, nil); err != nil {
				t.Errorf("%s %q variant: Decode: %v", tc.filename, variant, err)
				continue
			}

			wantFilename := filepath.FromSlash(tc.filename)
			if variant != "" {
				wantFilename += "." + variant
			}
			wantFilename += ".png"
			if overwriteTestdataFiles {
				if err := encodePNG(filepath.FromSlash(wantFilename), got); err != nil {
					t.Errorf("%s %q variant: encodePNG: %v", tc.filename, variant, err)
				}
				continue
			}
			want, err := decodePNG(wantFilename)
			if err != nil {
				t.Errorf("%s %q variant: decodePNG: %v", tc.filename, variant, err)
				continue
			}
			if err := checkApproxEqual(got, want); err != nil {
				t.Errorf("%s %q variant: %v", tc.filename, variant, err)
				continue
			}
		}
	}
}

func TestBlendColor(t *testing.T) {
	// This example comes from doc.go. Look for "orange" in the "Colors"
	// section.
	pal := Palette{
		2: color.RGBA{0xff, 0xcc, 0x80, 0xff}, // "Material Design Orange 200".
	}
	cReg := [64]color.RGBA{}
	got := BlendColor(0x40, 0x7f, 0x82).Resolve(&pal, &cReg)
	want := color.RGBA{0x40, 0x33, 0x20, 0x40} // 25% opaque "Orange 200", alpha-premultiplied.
	if got != want {
		t.Errorf("\ngot  %x\nwant %x", got, want)
	}
}
