package door

import (
	"strings"
	"testing"
)

func pctUpdate(pct *int64) func() int64 {
	return func() int64 {
		return *pct
	}
}

func TestBarsMatch(t *testing.T) {
	// verify that the BARS_CP437 matches BARS_UNICODE
	// When translated via CP437_to_Unicode().

	cp437 := BARS_CP437.solid
	convert := CP437_to_Unicode(cp437)
	unicode := BARS_UNICODE.solid
	if convert != unicode {
		t.Errorf("BARS solid: %#v != %#v\n", unicode, convert)
	}

	for half := 0; half < 2; half++ {
		cp437 := BARS_CP437.half[half]
		convert := CP437_to_Unicode(cp437)
		unicode := BARS_UNICODE.half[half]
		if convert != unicode {
			t.Errorf("BARS half[%d]: %#v != %#v\n", half, unicode, convert)
		}
	}

	for grad := 0; grad < 4; grad++ {
		cp437 := BARS_CP437.gradient[grad]
		convert := CP437_to_Unicode(cp437)
		unicode := BARS_UNICODE.gradient[grad]
		if convert != unicode {
			t.Errorf("BARS gradient[%d]: %#v != %#v\n", grad, unicode, convert)
		}
	}
}

func TestBarsUnicode(t *testing.T) {
	// Init as if we're in Unicode mode
	Unicode = true
	CP437 = false
	BARS = BARS_UNICODE
	testBars(t)
}

func TestBarsCP437(t *testing.T) {
	// Init as if we're in CP437 mode
	Unicode = false
	CP437 = true
	BARS = BARS_CP437
	testBars(t)
}

func testBars(t *testing.T) {
	// Generic function that tests output by building results
	// from BARS structure. (Can test Unicode and CP437.)

	BarColor := ColorText("BLUE")

	Bar25 := ColorText("RED")
	Bar50 := ColorText("BROWN")
	Bar75 := ColorText("BOLD YEL")
	Bar95 := ColorText("GREEN")
	Bar100 := ColorText("BRI GREEN")

	bar := BarLine{Line: Line{DefaultColor: BarColor}, Width: 10, Style: SOLID}
	bar.ColorRange = []BarRange{
		{2500, Bar25},
		{5000, Bar50},
		{7500, Bar75},
		{9500, Bar95},
		{10100, Bar100}}

	BarSolid := map[int]string{0: Bar25 + "          ",
		5:   Bar25 + "          ",
		10:  Bar25 + BARS.solid + "         ",
		20:  Bar25 + strings.Repeat(BARS.solid, 2) + "        ",
		25:  Bar25 + strings.Repeat(BARS.solid, 2) + "        ",
		30:  Bar50 + strings.Repeat(BARS.solid, 3) + "       ",
		50:  Bar50 + strings.Repeat(BARS.solid, 5) + "     ",
		75:  Bar75 + strings.Repeat(BARS.solid, 7) + "   ",
		90:  Bar95 + strings.Repeat(BARS.solid, 9) + " ",
		95:  Bar95 + strings.Repeat(BARS.solid, 9) + " ",
		100: Bar100 + strings.Repeat(BARS.solid, 10) + "",
	}

	for pct, text := range BarSolid {
		bar.Percent = int64(pct * 100)
		got := bar.Output()
		if got != text {
			t.Errorf("BarSolidRange: Expected %#v (%d%%), got %#v", text, pct, got)
		}
	}

	BarColor = ColorText("BLA ON WHI")
	bar = BarLine{Line: Line{DefaultColor: BarColor}, Width: 10, Style: HALF_STEP, PercentStyle: PERCENT_SPACE}
	BarHalf := map[int]string{0: BarColor + "     0%   ",
		5:   BarColor + BARS.half[1] + "    5%   ",
		6:   BarColor + BARS.half[1] + "    6%   ",
		10:  BarColor + BARS.half[0] + "   10%   ",
		20:  BarColor + BARS.half[0] + BARS.half[0] + "  20%   ",
		25:  BarColor + BARS.half[0] + BARS.half[0] + BARS.half[1] + " 25%   ",
		26:  BarColor + BARS.half[0] + BARS.half[0] + BARS.half[1] + " 26%   ",
		50:  BarColor + strings.Repeat(BARS.half[0], 3) + " 50%   ",
		75:  BarColor + strings.Repeat(BARS.half[0], 3) + " 75%   ",
		90:  BarColor + strings.Repeat(BARS.half[0], 3) + " 90% " + BARS.half[0] + " ",
		100: BarColor + strings.Repeat(BARS.half[0], 3) + " 100 " + strings.Repeat(BARS.half[0], 2),
	}

	for pct, text := range BarHalf {
		bar.Percent = int64(pct * 100)
		got := bar.Output()
		if got != text {
			t.Errorf("BarHalf: Expected %#v (%d%%), got %#v", text, pct, got)
		}
	}

	BarColor = ColorText("RED")
	bar = BarLine{Line: Line{DefaultColor: BarColor}, Width: 10, Style: GRADIENT}
	BarGrad := map[int]string{0: BarColor + "          ",
		3:   BarColor + BARS.gradient[1] + "         ",
		5:   BarColor + BARS.gradient[2] + "         ",
		8:   BarColor + BARS.gradient[3] + "         ",
		10:  BarColor + BARS.gradient[0] + "         ",
		20:  BarColor + BARS.gradient[0] + BARS.gradient[0] + "        ",
		25:  BarColor + BARS.gradient[0] + BARS.gradient[0] + BARS.gradient[2] + "       ",
		50:  BarColor + strings.Repeat(BARS.gradient[0], 5) + "     ",
		75:  BarColor + strings.Repeat(BARS.gradient[0], 7) + BARS.gradient[2] + "  ",
		100: BarColor + strings.Repeat(BARS.gradient[0], 10),
	}

	var percent int64
	bar.UpdateP = pctUpdate(&percent)

	for pct, text := range BarGrad {
		percent = int64(pct * 100)
		got := bar.Output()
		if got != text {
			t.Errorf("BarGradient: Expected %#v (%d%%), got %#v", text, pct, got)
		}
	}

}