import "minimal-polyfills/Object.fromEntries";
import * as fs from "fs";
import {
    join as pathJoin,
    relative as pathRelative,
    dirname as pathDirname,
    sep as pathSep
} from "path";
import { crawl } from "../src/bin/tools/crawl";
import { downloadKeycloakDefaultTheme } from "../src/bin/shared/downloadKeycloakDefaultTheme";
import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath";
import { rmSync } from "../src/bin/tools/fs.rmSync";

// NOTE: To run without argument when we want to generate src/i18n/generated_kcMessages files,
// update the version array for generating for newer version.

//@ts-ignore
const propertiesParser = require("properties-parser");

async function main() {
    const keycloakVersion = "24.0.4";

    const thisCodebaseRootDirPath = getThisCodebaseRootDirPath();

    const tmpDirPath = pathJoin(thisCodebaseRootDirPath, "tmp_xImOef9dOd44");

    rmSync(tmpDirPath, { recursive: true, force: true });

    fs.mkdirSync(tmpDirPath);

    fs.writeFileSync(
        pathJoin(tmpDirPath, ".gitignore"),
        Buffer.from("/*\n!.gitignore\n", "utf8")
    );

    await downloadKeycloakDefaultTheme({
        keycloakVersion,
        destDirPath: tmpDirPath,
        buildOptions: {
            cacheDirPath: pathJoin(
                thisCodebaseRootDirPath,
                "node_modules",
                ".cache",
                "keycloakify"
            ),
            npmWorkspaceRootDirPath: thisCodebaseRootDirPath
        }
    });

    type Dictionary = { [idiomId: string]: string };

    const record: { [typeOfPage: string]: { [language: string]: Dictionary } } = {};

    {
        const baseThemeDirPath = pathJoin(tmpDirPath, "base");
        const re = new RegExp(
            `^([^\\${pathSep}]+)\\${pathSep}messages\\${pathSep}messages_([^.]+).properties$`
        );

        crawl({
            dirPath: baseThemeDirPath,
            returnedPathsType: "relative to dirPath"
        }).forEach(filePath => {
            const match = filePath.match(re);

            if (match === null) {
                return;
            }

            const [, typeOfPage, language] = match;

            (record[typeOfPage] ??= {})[language.replace(/_/g, "-")] = Object.fromEntries(
                Object.entries(
                    propertiesParser.parse(
                        fs
                            .readFileSync(pathJoin(baseThemeDirPath, filePath))
                            .toString("utf8")
                    )
                ).map(([key, value]: any) => [
                    key === "locale_pt_BR" ? "locale_pt-BR" : key,
                    value.replace(/''/g, "'")
                ])
            );
        });
    }

    rmSync(tmpDirPath, { recursive: true });

    Object.keys(record).forEach(themeType => {
        const recordForPageType = record[themeType];

        if (themeType !== "login" && themeType !== "account") {
            return;
        }

        const baseMessagesDirPath = pathJoin(
            thisCodebaseRootDirPath,
            "src",
            themeType,
            "i18n",
            "baseMessages"
        );

        const languages = Object.keys(recordForPageType);

        const generatedFileHeader = [
            `//This code was automatically generated by running ${pathRelative(
                thisCodebaseRootDirPath,
                __filename
            )}`,
            "//PLEASE DO NOT EDIT MANUALLY"
        ].join("\n");

        languages.forEach(language => {
            const filePath = pathJoin(baseMessagesDirPath, `${language}.ts`);

            fs.mkdirSync(pathDirname(filePath), { recursive: true });

            fs.writeFileSync(
                filePath,
                Buffer.from(
                    [
                        generatedFileHeader,
                        "",
                        "/* spell-checker: disable */",
                        `const messages= ${JSON.stringify(
                            recordForPageType[language],
                            null,
                            2
                        )};`,
                        "",
                        "export default messages;",
                        "/* spell-checker: enable */"
                    ].join("\n"),
                    "utf8"
                )
            );

            //console.log(`${filePath} wrote`);
        });

        fs.writeFileSync(
            pathJoin(baseMessagesDirPath, "index.ts"),
            Buffer.from(
                [
                    generatedFileHeader,
                    `import * as en from "./en";`,
                    "",
                    "export async function getMessages(currentLanguageTag: string) {",
                    "    const { default: messages } = await (() => {",
                    "        switch (currentLanguageTag) {",
                    `            case "en": return en;`,
                    ...languages
                        .filter(language => language !== "en")
                        .map(
                            language =>
                                `            case "${language}": return import("./${language}");`
                        ),
                    '            default: return { "default": {} };',
                    "        }",
                    "    })();",
                    "    return messages;",
                    "}"
                ].join("\n"),
                "utf8"
            )
        );
    });
}

if (require.main === module) {
    main();
}