/**
 * 国际化模块,属于业务层
 */

import { Singleton, Container, Scope, Inject } from "typescript-ioc";
import { IService, logger } from "mslib"
import { TyGlobalApiClient, Token } from "./TyGlobalApi";
import { redisClient } from "./IORedisClient";
import Contants from "./Contants";
import { retry } from "./Decorators";

/**
 * 国际化服务类
 */
@Singleton
export class GlobalService {
    @Inject
    tyGlobalApiClient: TyGlobalApiClient;

    /**
     * 获取语言包
     */
    async getLanguagePacks(args: { token: Token, language?: string }): Promise<{
        [locale: string]: { key: string, value: string }[]
    }> {
        let apiResponse = await this.tyGlobalApiClient.get({
            token: args.token,
            type: 1
        });

        let languagePacks = { 'zh_CN': [] };
        let cn = new Map();

        for (const item of apiResponse.data?.data) {
            if (!languagePacks[item.language]) languagePacks[item.language] = [];

            languagePacks[item.language].push({ key: item.key, value: item.value });
            cn.set(item.key, item.cn);
        }

        for (const item of cn.entries()) {
            languagePacks['zh_CN'].push({ key: item[0], value: item[1] });
        }

        return languagePacks;
    }

    /**
     * 同步后端语言包到云端redis
     */
    async syncBackendLanguagePacks() {
        let packs = await this.getLanguagePacks({ token: Token.nonstandard_back_end });

        for (const key in packs) {
            await redisClient.hset('translation_1102011', key, JSON.stringify(packs[key]));
            logger.info(`同步非标/后端语言包到redis成功,lang:${key}`);

            if (Contants.IS_LOCAL_DEBUG) {
                await redisClient.hset('t_realtime_data', `translation_1102011:${key}_000`, JSON.stringify(packs[key]));
                await redisClient.hset('t_realtime_data', `translation_1102011:${key}_111`, JSON.stringify(packs[key]));
            }

            //反序列化校验
            if (Contants.IS_LOCAL_DEBUG) {
                try {
                    let value = await redisClient.hget('translation_1102011', key);
                    let obj = JSON.parse(value);
                    let i = 1;
                    logger.info(`校验redis语言包成功,lang:${key}`);
                } catch (error) {
                    logger.error(error);
                }
            }
        }
    }
}

/**
 * i18n国际化实例
 * 
 * 模块被加载时，从ioc读取配置config.global并自动创建该实例+初始化，如果未配置则为空
 * 
 * 用法：
 * 
 * i18n.__('(主相机)')
 * 
 * i18n.__('Hello %s', 'Keytop')
 * 
 * i18n.__('Hello {0}', ['Keytop'])
 * 
 * i18n.__('Hello {name}', { name: 'Keytop' })
 * 
 * i18n.__({ phrase: 'Hello %s', locale: 'en_US' }, 'Keytop1')
 * 
 * i18n.__({ phrase: 'Hello {0}', locale: 'en_US' }, ['Keytop1'])
 * 
 * i18n.__({ phrase: 'Hello {name}', locale: 'en_US' }, { name: 'Keytop1' })
 * 
 * https://www.npmjs.com/package/i18n
 */
export let i18n = null;

let config = Container.getValue('config.global');

if (config?.mode) {
    try {
        const { I18n } = require('i18n');
        i18n = new I18n();
    } catch (error) {
        logger.error('i18n实例化失败,请检查是否已安装插件i18n', error);
    }

    if (i18n) {
        setTimeout(async () => {
            try {
                await retry(async () => {
                    switch (config.mode.toUpperCase()) {
                        case 'CLOUD':
                            await init_i18n_cloud();
                            break;
                        case 'PARK':
                            await init_i18n_park();
                            break;
                    }

                    logger.info('i18n初始化成功');
                }, 3, 500, {
                    errorHandler: (error) => {
                        logger.error('i18n初始化失败', error);
                    }
                });
            } catch (error) {
                logger.error('i18n初始化失败', error);
            }
        });
    }
}

async function init_i18n_cloud() {
    let packs = await redisClient.hgetall('translation_1102011');
    let staticCatalog = {};
    let locales = [];

    for (const key in packs) {
        try {
            let pack = {};

            JSON.parse(packs[key]).forEach(s => {
                pack[s.key] = s.value;
            });

            locales.push(key);
            staticCatalog[key] = pack;
        } catch (error) {
            logger.error(`加载云端redis语言包失败,lang:${key}`, error);
        }
    }

    logger.info(`加载云端redis语言包成功,lang:${locales.join(',')}`);

    i18n.configure({
        defaultLocale: 'en_US',
        locales: locales,
        staticCatalog: staticCatalog,
        mustacheConfig: {
            tags: ['{', '}'],
            disable: false
        },
        logDebugFn: function (msg) {
            logger.debug(msg);
        },
        logWarnFn: function (msg) {
            // logger.warn(msg);
        },
        logErrorFn: function (msg) {
            logger.error(msg);
        },
        missingKeyFn: function (locale, value) {
            return value;
        },
    });
}

async function init_i18n_park() {
    let locale = 'en_US';

    //加载车场主语言
    if (!Contants.IS_LOCAL_DEBUG) {
        const knexInstance = require('knex')({
            client: 'sqlite3',
            connection: {
                filename: "/home/keytop/data/lotconfig.db"
            }
        });

        let configs = await knexInstance('t_config').where({ session: 'charge', name: 'countryAndLanguage' });
        if (configs && configs.length > 0 && configs[0].value) locale = configs[0].value;
    }

    let staticCatalog = {};
    {
        let fields: string[] = await redisClient.hkeys('t_realtime_data');
        let current_fields = fields.filter(s => s.startsWith(`translation_1102011:${locale}`))
        let pack = {};

        for (const field of current_fields) {
            let json = await redisClient.hget('t_realtime_data', field);
            JSON.parse(json).forEach(s => {
                pack[s.key] = s.value;
            });
        }

        staticCatalog[locale] = pack;
    }

    logger.info(`加载场端redis语言包成功,lang:${locale}`);

    i18n.configure({
        defaultLocale: locale,
        locales: [locale],
        staticCatalog: staticCatalog,
        mustacheConfig: {
            tags: ['{', '}'],
            disable: false
        },
        logDebugFn: function (msg) {
            logger.debug(msg);
        },
        logWarnFn: function (msg) {
            // logger.warn(msg);
        },
        logErrorFn: function (msg) {
            logger.error(msg);
        },
        missingKeyFn: function (locale, value) {
            return value;
        },
    });
}

/**
 * 翻译非标数据,翻译格式为${{xxx}}的字符串
 * 
 * 使用的语言包是非标/后端
 */
export function translateNsData(data: any, locale: string) {
    if (typeof data === 'object') {
        translateObj(data, locale);
        return data;
    } else {
        if (typeof data === 'string' && data.startsWith('${{') && data.endsWith('}}')) {
            return i18n.__({ phrase: data.substring(3, data.length - 2), locale: locale });
        } else {
            return data;
        }
    }
}

function translateObj(data: object, locale: string) {
    for (const key in data) {
        if (typeof data[key] === 'object') {
            translateObj(data[key], locale);
        } else {
            if (typeof data[key] === 'string' && data[key].startsWith('${{') && data[key].endsWith('}}')) {
                data[key] = i18n.__({ phrase: data[key].substring(3, data[key].length - 2), locale: locale });
            }
        }
    }
}