package test_core_text_i18n

import "core:mem"
import "core:fmt"
import "core:os"
import "core:testing"
import "core:text/i18n"

TEST_count := 0
TEST_fail  := 0

when ODIN_TEST {
	expect  :: testing.expect
	log     :: testing.log
} else {
	expect  :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
		TEST_count += 1
		if !condition {
			TEST_fail += 1
			fmt.printf("[%v] %v\n", loc, message)
			return
		}
	}
	log     :: proc(t: ^testing.T, v: any, loc := #caller_location) {
		fmt.printf("[%v] ", loc)
		fmt.printf("log: %v\n", v)
	}
}
T :: i18n.get

Test :: struct {
	section: string,
	key:     string,
	val:     string,
	n:       int,
}

Test_Suite :: struct {
	file:    string,
	loader:  proc(string, i18n.Parse_Options, proc(int) -> int, mem.Allocator) -> (^i18n.Translation, i18n.Error),
	err:     i18n.Error,
	options: i18n.Parse_Options,
	tests:   []Test,
}

TESTS := []Test_Suite{
	{
		file   = "assets/I18N/nl_NL.mo",
		loader = i18n.parse_mo_file,
		tests  = {
			// These are in the catalog.
			{ "", "There are 69,105 leaves here.", "Er zijn hier 69.105 bladeren.",  1 },
			{ "", "Hellope, World!",               "Hallo, Wereld!",                 1 },
			{ "", "There is %d leaf.\n",           "Er is %d blad.\n",               1 },
			{ "", "There are %d leaves.\n",        "Er is %d blad.\n",               1 },
			{ "", "There is %d leaf.\n",           "Er zijn %d bladeren.\n",        42 },
			{ "", "There are %d leaves.\n",        "Er zijn %d bladeren.\n",        42 },

			// This isn't in the catalog, so should ruturn the key.
			{ "", "Come visit us on Discord!",     "Come visit us on Discord!",      1 },
		},
	},

	// QT Linguist with default loader options.
	{
		file   = "assets/I18N/nl_NL-qt-ts.ts",
		loader = i18n.parse_qt_linguist_file,
		tests  = {
			// These are in the catalog.
			{ "Page",          "Text for translation",           "Tekst om te vertalen",        1},
			{ "Page",          "Also text to translate",         "Ook tekst om te vertalen",    1},
			{ "installscript", "99 bottles of beer on the wall", "99 flessen bier op de muur",  1},
			{ "apple_count",   "%d apple(s)",                    "%d appel",                    1},
			{ "apple_count",   "%d apple(s)",                    "%d appels",                  42},

			// These aren't in the catalog, so should ruturn the key.
			{ "",              "Come visit us on Discord!",      "Come visit us on Discord!",  1 },
			{ "Fake_Section",  "Come visit us on Discord!",      "Come visit us on Discord!",  1 },
		},
	},

	// QT Linguist, merging sections.
	{
		file    = "assets/I18N/nl_NL-qt-ts.ts",
		loader  = i18n.parse_qt_linguist_file,
		options = {merge_sections = true},
		tests   = {
			// All of them are now in section "", lookup with original section should return the key.
			{ "",              "Text for translation",           "Tekst om te vertalen",        1},
			{ "",              "Also text to translate",         "Ook tekst om te vertalen",    1},
			{ "",              "99 bottles of beer on the wall", "99 flessen bier op de muur",  1},
			{ "",              "%d apple(s)",                    "%d appel",                    1},
			{ "",              "%d apple(s)",                    "%d appels",                  42},

			// All of them are now in section "", lookup with original section should return the key.
			{ "Page",          "Text for translation",           "Text for translation",            1},
			{ "Page",          "Also text to translate",         "Also text to translate",          1},
			{ "installscript", "99 bottles of beer on the wall", "99 bottles of beer on the wall",  1},
			{ "apple_count",   "%d apple(s)",                    "%d apple(s)",                     1},
			{ "apple_count",   "%d apple(s)",                    "%d apple(s)",                    42},
		},
	},

	// QT Linguist, merging sections. Expecting .Duplicate_Key error because same key exists in more than 1 section.
	{
		file    = "assets/I18N/duplicate-key.ts",
		loader  = i18n.parse_qt_linguist_file,
		options = {merge_sections = true},
		err     = .Duplicate_Key,
	},

	// QT Linguist, not merging sections. Shouldn't return error despite same key existing in more than 1 section.
	{
		file    = "assets/I18N/duplicate-key.ts",
		loader  = i18n.parse_qt_linguist_file,
	},
}

@test
tests :: proc(t: ^testing.T) {
	using fmt

	cat: ^i18n.Translation
	err: i18n.Error

	for suite in TESTS {
		cat, err = suite.loader(suite.file, suite.options, nil, context.allocator)

		msg := fmt.tprintf("Expected loading %v to return %v, got %v", suite.file, suite.err, err)
		expect(t, err == suite.err, msg)

		if err == .None {
			for test in suite.tests {
				val := T(test.section, test.key, test.n, cat)

				msg  = fmt.tprintf("Expected key `%v` from section `%v`'s form for value `%v` to equal `%v`, got `%v`", test.key, test.section, test.n, test.val, val)
				expect(t, val == test.val, msg)
			}
		}
		i18n.destroy(cat)
	}
}

main :: proc() {
	using fmt

	track: mem.Tracking_Allocator
	mem.tracking_allocator_init(&track, context.allocator)
	context.allocator = mem.tracking_allocator(&track)

	t := testing.T{}
	tests(&t)

	fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
	if TEST_fail > 0 {
		os.exit(1)
	}

	if len(track.allocation_map) > 0 {
		println()
		for _, v in track.allocation_map {
			printf("%v Leaked %v bytes.\n", v.location, v.size)
		}
	}
}