"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.code2file = code2file;
exports.file2code = file2code;
exports.getLangData = getLangData;
const misc_1 = require("./misc");
const expiringCache_1 = require("./expiringCache");
const promises_1 = require("fs/promises");
const config_1 = require("./config");
const watchLoad_1 = require("./watchLoad");
const embedded_1 = __importDefault(require("./langs/embedded"));
const const_1 = require("./const");
const plugins_1 = require("./plugins");
const path_1 = require("path");
const lodash_1 = __importDefault(require("lodash"));
const PREFIX = 'hfs-lang-';
const SUFFIX = '.json';
function code2file(code) {
    return PREFIX + code.toLowerCase() + SUFFIX;
}
function file2code(fn) {
    return fn.replace(PREFIX, '').replace(SUFFIX, '');
}
const cache = (0, expiringCache_1.expiringCache)(3_000); // 3 seconds for both a good dx and acceptable performance
async function getLangData(ctxOrLangCsv) {
    if (typeof ctxOrLangCsv !== 'string') {
        const ctx = ctxOrLangCsv;
        const param = String(ctx.query.lang || '');
        if (!param && forceLangData)
            return forceLangData;
        ctxOrLangCsv = param || ctx.get('Accept-Language') || '';
    }
    const csv = ctxOrLangCsv.toLowerCase();
    return cache.try(csv, async () => {
        const langs = csv.split(',');
        const ret = {};
        let i = 0;
        while (i < langs.length) {
            let k = langs[i] || ''; // shut up ts
            if (!k || k === const_1.EMBEDDED_LANGUAGE)
                break;
            const fn = code2file(k);
            try {
                ret[k] = JSON.parse(await (0, promises_1.readFile)(fn, 'utf8'));
            } // allow external files to override embedded translations
            catch {
                if ((0, misc_1.hasProp)(embedded_1.default, k))
                    ret[k] = lodash_1.default.cloneDeep(embedded_1.default[k]);
                else {
                    do {
                        k = k.substring(0, k.lastIndexOf('-'));
                    } while (k && langs.includes(k));
                    if (k) {
                        langs[i] = k; // overwrite and retry
                        continue;
                    }
                }
            }
            const fromPlugins = (0, misc_1.onlyTruthy)(await Promise.all((0, plugins_1.mapPlugins)(async (pl) => (0, misc_1.tryJson)(await (0, promises_1.readFile)((0, path_1.join)(pl.folder, fn), 'utf8').catch(() => ''))?.translate)));
            if (fromPlugins.length)
                lodash_1.default.defaults((ret[k] ||= {}).translate ||= {}, ...fromPlugins); // be sure we have an entry for k
            i++;
        }
        return ret;
    });
}
let forceLangData;
let undo;
(0, config_1.defineConfig)(misc_1.CFG.force_lang, '', v => {
    undo?.();
    if (!v)
        return forceLangData = undefined;
    const translation = embedded_1.default[v];
    forceLangData = { [v]: translation };
    if (v === const_1.EMBEDDED_LANGUAGE)
        return;
    const res = (0, watchLoad_1.watchLoad)(code2file(v), data => {
        forceLangData = { [v]: (0, misc_1.tryJson)(data) || translation };
    });
    undo = res.unwatch;
});
