const Locale = (function () {
    let localeData = {};
    let loadedLocale = "en";
    let translatorMode = false;
    let missingTranslations = {};
    let obj = {
        MonthsOfYear: ["Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"],
        DaysOfWeek: ["Mon", "Tue", "Wed", "Thurs", "Fri", "Sat", "Sun"],
        LongDaysOfWeek: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
        AvailableLocales: ["en"],
        LoadLocale: async function (iso) {
            let data = await (await fetch(`/Locale/${iso}.json`)).json();
            loadedLocale = data.LocaleName;
            localeData = data.Strings;
            this.MonthsOfYear = data.MonthsOfYear || this.MonthsOfYear;
            this.DaysOfWeek = data.DaysOfWeek || this.DaysOfWeek;
            this.LongDaysOfWeek = data.LongDaysOfWeek || this.LongDaysOfWeek;
        },
        GetLocaleMessage: function (original) {
            if (translatorMode && !(original in missingTranslations)) {
                missingTranslations[original] = "";
                localeData[original] = original;
                console.log(`Missing translation for '${original}'`);
            }
            return localeData[original] || original;
        },
        SetTranslatorMode: function (value) {
            translatorMode = value;
            this.ApplyLocale();
            console.log(`Translator mode ${value ? "enabled" : "disabled"}.`)
        },
        ApplyLocale: function (context) {
            $((context || "body") + " *")
                .contents()
                .filter((_, e) => e.nodeType === Node.TEXT_NODE && e.textContent.match(/[a-zA-Z]\w/) && !e.textContent.contains("<!-- ko"))
                .each(function (_, e) {
                    e.textContent = e.textContent.replace(/^(\s*)([a-zA-Z ].+?)(\s*)$/, (match, p1, p2, p3) => `${p1}${obj.GetLocaleMessage(p2)}${p3}`);
                });
        },
        ListLocale: function (context) {
            let messages = {};
            $((context || "body") + " *")
                .contents()
                .filter((_, e) => e.nodeType === Node.TEXT_NODE && e.textContent.match(/[a-zA-Z]\w/) && !e.textContent.contains("<!-- ko"))
                .each(function (_, e) {
                    e.textContent = e.textContent.replace(/^(\s*)([a-zA-Z ].+?)(\s*)$/, function (match, p1, p2, p3) {
                        messages[p2] = p2;
                        return `${p1}${p2}${p3}`
                    });
                });
            console.log(JSON.stringify(messages, null, 4));
        },
        DownloadJSONFile: function () {
            const output = {
                MonthsOfYear: this.MonthsOfYear,
                DaysOfWeek: this.DaysOfWeek,
                LongDaysOfWeeek: this.LongDaysOfWeek,
                LocaleName: loadedLocale,
                Strings: localeData,
            };
            const jsonData = JSON.stringify(output);
            const blob = new Blob([jsonData], {
                type: 'application/json'
            });
            saveAs(blob, loadedLocale + ".json");
        },
        DownloadPOTFile: function () {
            let lines = [];
            for (const key of Object.keys(missingTranslations)) {
                lines.push(`msgid "${key}"`);
                lines.push(`msgstr ""`);
            }
            const output = lines.join("\n");
            const blob = new Blob([output], {
                type: 'text/plain'
            });
            saveAs(blob, "amp.pot");
        },
        SwitchLocale: async function (iso) {
            if (iso == loadedLocale) { return; }
            /* If the already loaded locale is not English then we need to reload
             * the page and apply the locale after reload. */
            else if (loadedLocale != "en") {
                localStorage.AMPLocale = iso == "en" ? "" : iso;
                location.reload();
                return;
            }
            localStorage.AMPLocale = iso;
            await obj.LoadLocale(iso);
            obj.ApplyLocale();
        }, 
        AutoLoadLocale: async function (override) {
            if (override == "en") {
                localStorage.AMPLocale = "";
                return;
            }

            if (override != null) {
                await this.SwitchLocale(override);
            }
            else if ("AMPLocale" in localStorage && localStorage.AMPLocale != "") {
                await this.SwitchLocale(localStorage.AMPLocale);
            }
        },
    };

    obj.l = obj.GetLocaleMessage;

    return obj;
})();