-- import addon read namespace from global env
local _G = _G
local Grichelde = _G.Grichelde or {}

local find, pairs, tSize, cRed, cGreen, format = Grichelde.F.find, Grichelde.F.pairs, Grichelde.F.tSize, Grichelde.F.cRed, Grichelde.F.cGreen, Grichelde.F.format

function Grichelde:TestMatch(text, pattern)
    -- disable debug print out for testing
    local oldLogLevel = Grichelde.logLevel
    Grichelde.logLevel = 0

    local pos1, pos2, cap1, cap2, cap3, cap4, cap5, cap6, cap7, cap8, cap9 = find(text, pattern)
    self:PrefixedPrint("TestMatch : text: %s, pattern: %s, pos1: %d, pos2: %d", text, pattern, pos1, pos2)
    self:PrefixedPrint("TestMatch : cap1: %s, cap2: %s, cap3: %s, cap4: %s, cap5: %s, cap6: %s, cap7: %s, cap8: %s, cap9: %s", cap1, cap2, cap3, cap4, cap5, cap6, cap7, cap8, cap9)

    -- restore old loglevel
    Grichelde.logLevel = oldLogLevel
end

function Grichelde:RunTests()
    local function test(name, replacements, testData, replaceEmotes)
        local i, ok, size = 0, 0, tSize(testData)
        for input, expected in pairs(testData) do
            local actual = self:ReplaceText(input, replacements, replaceEmotes or false)
            i = i + 1
            if (actual == expected) then
                ok = ok + 1
                self:PrefixedPrint("Test \"%s\" (%d/%d) %s: \"%s\" => \"%s\"", name, i, size, cGreen("passed"), input, expected)
            else
                self:PrefixedPrint("Test \"%s\" (%d/%d) %s: \"%s\" => \"%s\", but was \"%s\"", name, i, size, cRed("failed"), input, expected, actual)
            end
        end
        return ok, size
    end

    -- disable debug print out for testing
    local oldLogLevel = Grichelde.logLevel
    Grichelde.logLevel = 0

    local ok, all, o, a = 0, 0, 0, 0

    -- basic tests
    o, a = test(
        "fehlender Unterkiefer",
        {
            replacement_10 = {
                order = 10,
                searchText = "s",
                replaceText = "ch",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["abc"] = "abc",
            ["soo"] = "choo",
            ["oos"] = "ooch",
            ["oso"] = "ocho",
            ["sos"] = "choch",
            ["ssoo"] = "choo",
            ["osso"] = "ocho",
            ["ooss"] = "ooch",
            ["ABC"] = "ABC",
            ["Soo"] = "Choo",
            ["ooS"] = "ooCH",
            ["oSo"] = "oCho",
            ["SOS"] = "CHOCH",
            ["SSoo"] = "CHoo",
            ["OSSO"] = "OCHO",
            ["ooSS"] = "ooCH",
            ["schmeissen"] = "chmeichen",
            ["Schön"] = "Chön",
        }
    )
    ok = ok + o
    all = all + a

    -- case sensivity and extended replacements
    o, a = test(
        "Zark",
        {
            replacement_10 = {
                order = 10,
                searchText = "Zark",
                replaceText = "Schami",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["Zark"] = "Schami",
            ["ZARK"] = "SCHAMI",
            ["Zarkilein"] = "Schamiilein",
            ["ZARKILEIN"] = "SCHAMIILEIN",
            ["Zark!"] = "Schami!",
            ["ZARK!"] = "SCHAMI!",
            ["Zark ist tot"] = "Schami ist tot",
            ["ZARK ist tot"] = "SCHAMI ist tot",
            ["Zark ist der Tod"] = "Schami ist der Tod",
            ["ZARK IST DER TOD"] = "SCHAMI IST DER TOD",
        }
    )
    ok = ok + o
    all = all + a

    -- start/end of sentence/words
    o, a = test(
        "wann",
        {
            replacement_10 = {
                order = 10,
                searchText = "bcd",
                replaceText = "efg",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "uio",
                replaceText = "bnm",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "hij",
                replaceText = "klm",
                exactCase = false,
                consolidate = true,
                matchWhen = 4,
                stopOnMatch = false,
            },
            replacement_13 = {
                order = 13,
                searchText = "nop",
                replaceText = "qrs",
                exactCase = false,
                consolidate = true,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_14 = {
                order = 14,
                searchText = "tuv",
                replaceText = "wxy",
                exactCase = false,
                consolidate = true,
                matchWhen = 6,
                stopOnMatch = false,
            },
            replacement_15 = {
                order = 15,
                searchText = "wer",
                replaceText = "sdf",
                exactCase = false,
                consolidate = true,
                matchWhen = 7,
                stopOnMatch = false,
            },
        },
        {
            -- replacement_10
            ["bcd"] = "efg",
            ["abcdz"] = "aefgz",
            ["abcd"] = "aefg",
            ["bcdz"] = "efgz",
            -- replacement_11
            ["uio"] = "bnm",
            ["auioz"] = "auioz",
            ["auio"] = "auio",
            ["uioz"] = "uioz",
            -- replacement_12
            ["hij"] = "klm",
            ["ahijz"] = "ahijz",
            ["ahij"] = "ahij",
            ["hijz"] = "klmz",
            -- replacement_13
            ["nop"] = "qrs",
            ["anopz"] = "anopz",
            ["anop"] = "aqrs",
            ["nopz"] = "nopz",
            -- replacement_14
            ["tuv"] = "wxy",
            ["atuvz"] = "atuvz",
            ["atuv"] = "awxy",
            ["tuvz"] = "wxyz",
            -- replacement_15
            ["wer"] = "wer",
            ["awerz"] = "asdfz",
            ["awer"] = "awer",
            ["werz"] = "werz",

            -- replacement_10
            ["bcd abcdz abcd bcdz"] = "efg aefgz aefg efgz",
            -- replacement_11
            ["uio auioz auio uioz"] = "bnm auioz auio uioz",
            -- replacement_12
            ["hij ahijz ahij hijz"] = "klm ahijz ahij klmz",
            -- replacement_13
            ["nop anopz anop nopz"] = "qrs anopz aqrs nopz",
            -- replacement_14
            ["tuv atuvz atuv tuvz"] = "wxy atuvz awxy wxyz",
            -- replacement_15
            ["wer awerz awer werz"] = "wer asdfz awer werz",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "consolidate",
        {
            replacement_10 = {
                order = 10,
                searchText = "a",
                replaceText = "b",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "b",
                replaceText = "c",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "d",
                replaceText = "e",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["aaa"] = "c",
            ["abb"] = "c",
            ["abc"] = "c",
            ["bbc"] = "c",
            ["ace"] = "ce",
            ["abe"] = "ce",
            ["bbe"] = "ce",
            ["ece"] = "ece",
            ["ede"] = "ee",
        }
    )
    ok = ok + o
    all = all + a

    -- stop on match
    o, a = test(
        "stopOnMatch",
        {
            replacement_10 = {
                order = 10,
                searchText = "a",
                replaceText = "b",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = true,
            },
            replacement_11 = {
                order = 11,
                searchText = "b",
                replaceText = "c",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "c",
                replaceText = "d",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = true,
            },
        },
        {
            ["aaa"] = "bbb",
            ["abc"] = "bbc",
            ["bbc"] = "ddd",
            ["bca"] = "bcb",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "Jar Jar Binks (DE)",
        {
            replacement_10 = {
                order = 10,
                searchText = "ver",
                replaceText = "va",
                exactCase = false,
                consolidate = false,
                matchWhen = 4,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "en",
                replaceText = "'n",
                exactCase = false,
                consolidate = false,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "er",
                replaceText = "a",
                exactCase = false,
                consolidate = false,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_13 = {
                order = 13,
                searchText = "(%w?)ich",
                replaceText = "%1ichse",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_14 = {
                order = 14,
                searchText = "(d?m?)ir",
                replaceText = "%1ichse",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_15 = {
                order = 15,
                searchText = "du",
                replaceText = "du da",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_16 = {
                order = 16,
                searchText = "er",
                replaceText = "erse",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_17 = {
                order = 17,
                searchText = "sie",
                replaceText = "sie da",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_18 = {
                order = 18,
                searchText = "wir",
                replaceText = "wirse",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_19 = {
                order = 19,
                searchText = "ihr",
                replaceText = "ihrse",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_20 = {
                order = 20,
                searchText = "nicht",
                replaceText = "nich",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_21 = {
                order = 21,
                searchText = "die",
                replaceText = "de",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
        },
        {
            ["Ich kann dich verstehen."] = "Ichse kann dichse vasteh'n.",
            ["Wir haben sie die ganze Zeit über nicht verstanden"] = "Wirse hab'n sie da de ganze Zeit üba nich vastand'n",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "Stottern 1",
        {
            replacement_10 = {
                order = 10,
                searchText = "^([^aeiouy]-)([aeiouy])",
                replaceText = "%1%2-%1%2-%1%2",
                exactCase = false,
                consolidate = true,
                matchWhen = 4,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "([^bwp%s]-)([bwp])",
                replaceText = "%1%2-%1%2-%1%2",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["Ich mag dich."] = "I-I-Ich mag dich.",
            ["Dich mag ich."] = "Di-Di-Dich mag ich.",
            ["Bmm rrpss w"] = "B-B-Bmm rrp-rrp-rrpss w-w-w",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "trollifier",
        {
            replacement_10 = {
                order = 10,
                searchText = "(%w)(%p?)$",
                replaceText = "%1, mon%2",
                exactCase = false,
                consolidate = false,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "th",
                replaceText = "d",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "what are you",
                replaceText = "whatcha",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_13 = {
                order = 13,
                searchText = "your?s?",
                replaceText = "ya",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_14 = {
                order = 14,
                searchText = "going to",
                replaceText = "gonna",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_15 = {
                order = 15,
                searchText = "want to",
                replaceText = "wanna",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_16 = {
                order = 16,
                searchText = "ing",
                replaceText = "in'",
                exactCase = false,
                consolidate = true,
                matchWhen = 5,
                stopOnMatch = false,
            },
        },
        {
            ["What are you going to do when they come for you?"] = "Whatcha gonna do when dey come for ya, mon?",
            ["That's what young people are doing"] = "Dat's what young people are doin', mon",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "Jar Jar Binks (EN)",
        {
            replacement_10 = {
                order = 10,
                searchText = "me",
                replaceText = "mesa",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "I am",
                replaceText = "Mesa",
                exactCase = true,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "I'm",
                replaceText = "Mesa",
                exactCase = true,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_13 = {
                order = 13,
                searchText = "I",
                replaceText = "Me",
                exactCase = true,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_14 = {
                order = 14,
                searchText = "you are",
                replaceText = "yousa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_15 = {
                order = 15,
                searchText = "you're",
                replaceText = "yousa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_16 = {
                order = 16,
                searchText = "your",
                replaceText = "yous",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_17 = {
                order = 17,
                searchText = "(s?)he is",
                replaceText = "%1hesa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_18 = {
                order = 18,
                searchText = "(s?)he's",
                replaceText = "%1hesa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_19 = {
                order = 19,
                searchText = "they",
                replaceText = "daysa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_20 = {
                order = 20,
                searchText = "them",
                replaceText = "them-sa",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_21 = {
                order = 21,
                searchText = "ing",
                replaceText = "in'",
                exactCase = false,
                consolidate = true,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_22 = {
                order = 22,
                searchText = "the",
                replaceText = "da",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_23 = {
                order = 23,
                searchText = "th",
                replaceText = "d",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_24 = {
                order = 24,
                searchText = "yes",
                replaceText = "yesa",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_25 = {
                order = 25,
                searchText = "oka?y?",
                replaceText = "okeeday",
                exactCase = false,
                consolidate = false,
                matchWhen = 3,
                stopOnMatch = false,
            },
        },
        {
            ["I hear your voice through the thrilling grapewine."] = "Me hear yous voice drough da drillin' grapewine.",
            ["They gave them their OK"] = "Daysa gave dem-sa deir OKEEDAY",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "old-fashioned",
        {
            replacement_10 = {
                order = 10,
                searchText = "oi",
                replaceText = "oy",
                exactCase = false,
                consolidate = true,
                matchWhen = 2,
                stopOnMatch = false,
            },
            replacement_11 = {
                order = 11,
                searchText = "([^aeiou]*)([aeiou])",
                replaceText = "%1%2e",
                exactCase = false,
                consolidate = true,
                matchWhen = 5,
                stopOnMatch = false,
            },
            replacement_12 = {
                order = 12,
                searchText = "yours",
                replaceText = "thy",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
            replacement_13 = {
                order = 13,
                searchText = "youe",
                replaceText = "thou",
                exactCase = false,
                consolidate = true,
                matchWhen = 3,
                stopOnMatch = false,
            },
        },
        {
            ["Do you want to kill yours?"] = "Doe thou want toe kill thy?",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "emote detection on",
        {
            replacement_10 = {
                order = 10,
                searchText = "r",
                replaceText = "rr",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["Der Herr Richter *schaut Herrn Richter an*"] = "Derr Herrrr Rrichterr *schaut Herrn Richter an*",
            ["*schaut Herrn Richter an*"] = "*schaut Herrn Richter an*",
        }
    )
    ok = ok + o
    all = all + a

    o, a = test(
        "emote detection ignored",
        {
            replacement_10 = {
                order = 10,
                searchText = "r",
                replaceText = "rr",
                exactCase = false,
                consolidate = false,
                matchWhen = 2,
                stopOnMatch = false,
            },
        },
        {
            ["Der Herr Richter *schaut Herrn Richter an*"] = "Derr Herrrr Rrichterr *schaut Herrrrn Rrichterr an*",
            ["*schaut Herrn Richter an*"] = "*schaut Herrrrn Rrichterr an*",
        },
        true
    )
    ok = ok + o
    all = all + a

    if (ok == all) then
        self:PrefixedPrint("All %d tests %s", all, cGreen("passed"))
    else
        self:PrefixedPrint("%d test %s, %d tests %s", all - ok, cRed("failed"), ok, cGreen("passed"))
    end

    -- restore old loglevel
    Grichelde.logLevel = oldLogLevel
end