import { debug, error, info, warn } from 'ioium';
import { deepAssign, getByString } from 'utilium';
import en from '../locales/en.json' with { type: 'json' };
const loadedLocales = Object.assign(Object.create(null), { en });
/**
 * Add translations to a locale.
 * Note that translations are rendered as HTML, only replacements are escaped.
 */
export function extendLocale(locale, data) {
    if (!loadedLocales[locale]) {
        info('Adding new locale (no built-in): ' + locale);
        loadedLocales[locale] = {};
    }
    else
        debug('Extending locale: ' + locale);
    deepAssign(loadedLocales[locale], data);
}
let currentLoaded = en;
/**
 * Current locale
 */
export let currentLocale = 'en';
let currentRegionNames;
export function countryName(code) {
    return currentRegionNames.of(code);
}
let currentDateFields;
export function dateField(name) {
    return currentDateFields.of(name);
}
let currentConjunction;
export function conjoin(list) {
    return currentConjunction.format(list);
}
let currentDisjunction;
export function disjoin(list) {
    return currentDisjunction.format(list);
}
export let currentMonthNames;
export function useLocale(newLocale) {
    if (!loadedLocales[newLocale])
        throw new Error('Locale is not available: ' + newLocale);
    currentLocale = newLocale;
    currentLoaded = loadedLocales[newLocale];
    currentRegionNames = new Intl.DisplayNames(newLocale, { type: 'region' });
    currentDateFields = new Intl.DisplayNames(newLocale, { type: 'dateTimeField' });
    currentConjunction = new Intl.ListFormat(newLocale, { style: 'long', type: 'conjunction' });
    currentDisjunction = new Intl.ListFormat(newLocale, { style: 'long', type: 'disjunction' });
    const formatter = new Intl.DateTimeFormat(newLocale, { month: 'long' });
    currentMonthNames = Array.from({ length: 12 }, (_, monthIndex) => formatter.format(new Date(Date.UTC(2000, monthIndex + 1, 1))));
}
useLocale('en');
const localeReplacement = /\{(\w+)\}/g;
const escapePattern = /[&<>"']/g;
const escapes = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
};
export function escape(text) {
    return text.replaceAll(escapePattern, ch => escapes[ch]);
}
/**
 * Get localized text for a given translation key
 * @example
 * ```ts
 * text(`example.translation.key.${dynamicPart}`, { a: 1, b: 2 });
 * ```
 */
export function text(key, ...args) {
    const values = Object.assign(Object.create(null), args[0]);
    let text = getByString(currentLoaded, key) || values.$default;
    if (!text && currentLocale != 'en') {
        warn(`Missing translation in ${currentLocale}: ` + key);
        text = getByString(en, key);
    }
    if (!text) {
        error('Missing translation for key: ' + key);
        text = `?${key}?`;
    }
    if (typeof text == 'object') {
        error('Invalid translation key: ' + key);
        text = values.$default || `!${key}!`;
    }
    return text.replaceAll(localeReplacement, (_, name) => {
        if (!Object.hasOwn(values, name)) {
            console.error(new Error(`Missing replacement value for ${key}: ${name}`));
            values[name] = `<missing: ${name}>`;
        }
        return values.$html ? escape(String(values[name])) : String(values[name]);
    });
}
