import { getCookie } from "./cookie";
import { get } from "./request";
import { nullOrEmpty } from "./strings";

let cache;

function getCurrentLgId() {
    let lgid;
    if (typeof consts !== 'undefined') {
        lgid = getCookie(consts.cookie?.lang);
        if (nullOrEmpty(lgid)) {
            lgid = consts.user?.language;
        }
    }
    if (nullOrEmpty(lgid)) {
        lgid = getCookie('lgid');
    }
    if (nullOrEmpty(lgid)) {
        lgid = navigator.language || 'en-us';
    }
    lgid = lgid.toLowerCase().replace(/-/g, '_');
    if (nullOrEmpty(lgid)) {
        lgid = 'en';
    }
    switch (lgid) {
        case 'en_au':
        case 'en_ca':
        case 'fr_ca':
        case 'zh_cn':
            return lgid;
    }
    const lang = lgid.split('_')[0];
    switch (lang) {
        case 'en':
        case 'es':
        case 'fr':
        case 'pt':
            return lang;
        case 'zh':
            return 'zh_cn';
    }
    return 'en';
}

function getStorageKey(lgid) {
    if (typeof consts !== 'undefined') {
        return (consts.prefix || '') + `res_${lgid}`;
    }
    return `res_${lgid}`;
}

async function doRefreshLgres(template = '') {
    const lgid = getCurrentLgId();
    const url = template.length > 0 ? template.replace('{lgid}', lgid) : `language/${lgid}`;
    const r = await get(url);
    const dict = await r.json();
    localStorage.setItem(getStorageKey(lgid), JSON.stringify(dict));
    return dict;
}

async function refreshLgres(template, lgres) {
    if (lgres == null || typeof consts === 'undefined') {
        lgres = await doRefreshLgres(template);
    }
    const ver = Number(consts.resver);
    const currentVer = Number(lgres.ver);
    if (isNaN(currentVer) || isNaN(ver) || ver > currentVer) {
        console.log(`found new language res version: ${lgres.ver} => ${consts.resver}`);
        lgres = await doRefreshLgres(template);
    }
    Object.defineProperty(lgres, 'r', {
        writable: false,
        configurable: false,
        enumerable: false,
        value: function (key, defaultValue) {
            return getLanguage(this, key, defaultValue);
        }
    });
    cache = lgres;
    return lgres;
}

function getLanguage(lgres, key, defaultValue) {
    let value = lgres[key];
    return value ?? defaultValue;
}

function applyLanguage(dom, result) {
    for (let text of dom.querySelectorAll('[data-lgid]')) {
        const key = text.dataset.lgid;
        if (text.tagName === 'INPUT') {
            text.value = getLanguage(result, key, text.value);
        } else {
            text.innerText = getLanguage(result, key, text.innerText);
        }
        // delete text.dataset.lgid;
        text.dataset.lgid = '';
    }
    for (let title of dom.querySelectorAll('[data-title-lgid]')) {
        const key = title.dataset.titleLgid;
        title.setAttribute('title', getLanguage(result, key, title.getAttribute('title')));
        // delete title.dataset.titleLgid;
        title.dataset.titleLgid = '';
    }
    for (let holder of dom.querySelectorAll('[data-placeholder-lgid]')) {
        const key = holder.dataset.placeholderLgid;
        holder.setAttribute('placeholder', getLanguage(result, key, holder.getAttribute('placeholder')));
        // delete holder.dataset.placeholderLgid;
        holder.dataset.placeholderLgid = '';
    }
}

export function domLoad() {
    if (document.readyState === 'loading') {
        return new Promise((resolve, reject) => {
            let tid = setTimeout(() => reject('timeout'), 30000);
            document.addEventListener('DOMContentLoaded', () => {
                clearTimeout(tid);
                tid = void 0;
                resolve();
            });
        });
    }
    return Promise.resolve();
}

export async function init(dom = document.body, options = {}) {
    const lgid = getCurrentLgId();
    let lgres = localStorage.getItem(getStorageKey(lgid));
    let result;
    if (lgres != null) {
        try {
            lgres = JSON.parse(lgres);
            result = await refreshLgres(options.template, lgres);
        } catch (e) {
            console.error('error while parsing lgres, try refresh ...', e);
            result = await refreshLgres(options.template);
        }
    } else {
        result = await refreshLgres(options.template);
    }

    try {
        await domLoad();
        if (typeof options.callback === 'function') {
            options.callback(result);
        }
        applyLanguage(dom, result);
        return result;
    } catch (err) {
        console.error('error while loading language res ...', err);
    }
}

export function r(key, defaultValue) {
    if (cache != null) {
        return getLanguage(cache, key, defaultValue);
    }
    return defaultValue;
}

export const lang = {
    get current() {
        return getCurrentLgId();
    },
    get unknownError() {
        return r('unknownError', 'An unknown error occurred, please contact the administrator.');
    },
    get savedSuccessfully() {
        return r('savedSuccessfully', 'Saved successfully.');
    }
}