/*!
 * Built by ShiftSoftware
 * Copyright (c)
 */
import { Build } from "@stencil/core";
import { version } from "../../../package.json";
import localeNetworkMapper from "../../locale-mapper";
import globalSchema from "../../locales/type";
import errorsSchema from "../../locales/errors/type";
import { languageMapper } from "./types";
import formsSchema from "../../locales/forms/type";
const cachedLocales = {};
export async function getSharedLocal(languageKey) {
    const [errors, globalKeys] = await Promise.all([getLocaleLanguage(languageKey, 'errors', errorsSchema), getLocaleLanguage(languageKey, '-', globalSchema)]);
    return Object.assign({ errors }, globalKeys);
}
export async function getSharedFormLocal(languageKey) {
    const [errors, globalKeys, sharedFormKeys] = await Promise.all([
        getLocaleLanguage(languageKey, 'errors', errorsSchema),
        getLocaleLanguage(languageKey, '-', globalSchema),
        getLocaleLanguage(languageKey, 'forms*', formsSchema),
    ]);
    return Object.assign(Object.assign(Object.assign({}, globalKeys), sharedFormKeys), errors);
}
export async function getLocaleLanguage(languageKey, component, schema) {
    const languageFile = languageMapper[languageKey] || languageMapper.en;
    const localeFiles = localeNetworkMapper[component];
    if (!localeFiles || !localeFiles.length)
        throw new Error(`Locale file not found for component: ${component}`);
    if (localeFiles.length === 1) {
        const localeFile = localeFiles[0] + languageFile;
        const response = await requestLocaleFile(localeFile);
        try {
            schema.validateSync(response, { strict: true, abortEarly: false });
        }
        catch (error) {
            console.error(`Failed to parse locale file: ${localeFile}`);
            console.error(error);
        }
        return response;
    }
    else {
        const localeFilePromises = localeFiles.map(localeFile => requestLocaleFile(localeFile + languageFile));
        const localeFilesResponses = await Promise.all(localeFilePromises);
        const responseBluePrint = schema.getDefault();
        const parsedResponseMapper = {};
        recursiveParser(component, responseBluePrint, parsedResponseMapper, languageFile);
        try {
            schema.validateSync(parsedResponseMapper, { strict: true, abortEarly: false });
        }
        catch (error) {
            console.error(`Failed to parse locale file component: ${component}`);
            console.error(error);
        }
        return localeFilesResponses;
    }
}
function isPlainObject(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function recursiveParser(parents, bluePrint, parsedResponseMapper, languageFile) {
    let mappedSelf = false;
    Object.entries(bluePrint).forEach(([key, value]) => {
        if (typeof value === 'string' && !mappedSelf) {
            if (localeNetworkMapper[parents]) {
                const cacheKey = localeNetworkMapper[parents][0] + languageFile;
                if (cachedLocales[cacheKey])
                    Object.assign(parsedResponseMapper, cachedLocales[cacheKey]);
            }
            mappedSelf = true;
        }
        else if (isPlainObject(value)) {
            const childMapperKey = parents + '.' + key;
            const isNestedObject = Object.entries(value).some(([_, nestedValue]) => isPlainObject(nestedValue));
            if (isNestedObject) {
                parsedResponseMapper[key] = {};
                recursiveParser(childMapperKey, value, parsedResponseMapper[key], languageFile);
            }
            else if (localeNetworkMapper[childMapperKey] && !!localeNetworkMapper[childMapperKey].length) {
                const cacheKey = localeNetworkMapper[childMapperKey][0] + languageFile;
                if (cachedLocales[cacheKey])
                    parsedResponseMapper[key] = cachedLocales[cacheKey];
            }
        }
    });
}
async function requestLocaleFile(localeFile) {
    if (cachedLocales[localeFile])
        return await cachedLocales[localeFile];
    try {
        const fetchPromise = (Build.isDev ? fetch('http://localhost:3000/' + localeFile) : fetch(`https://cdn.jsdelivr.net/npm/adp-web-components@${version}/dist/${localeFile}`)).then(res => {
            if (!res.ok)
                delete cachedLocales[localeFile];
            return res.json();
        });
        cachedLocales[localeFile] = fetchPromise;
        const result = await fetchPromise;
        cachedLocales[localeFile] = result;
        return result;
    }
    catch (error) {
        delete cachedLocales[localeFile];
        return {};
    }
}
