import { _decorator} from 'cc';
import { director } from 'cc';
import { Polyglot } from './polyglot.min';
import { Singleton } from '../../manager/Singleton';
import { Logger } from '../../../extend/Logger';
import LocalizedLabel from './LocalizedLabel';
import LocalizedSprite from './LocalizedSprite';
import { Constants } from '../../../data/Constants';
const { ccclass, property } = _decorator;

//默认的多语言 必须是存在于数组i18n.languages中的
const curLang: string = 'en';
//缓存选择的多语言的key
const langCacheKey: string = `${Constants.gameName}CurLang`;

/**事例
 * 1、切换语言调用:
 * let languages = Object.keys(i18n.languages);
   let count: number = (languages.indexOf(i18n.curLang) + 1) % languages.length;
   i18n.init(languages[count]);

   2、切换了语言整个页面刷新语言 调用:
   i18n.updateSceneRenderers();

   3、lable多语言 直接挂载LocalizedLabel类 到lable节点上 然后填入id，
   这个id是多语言中i18n.languages.en 例如
   "lottery": {
        "title": "Wheel of fortune",
        "free": "Free"
    },就是 填入“lottery.title”

    4、打当lable文本是动态的时候，比如”你完成了多少个个订单“ 这儿就需要你在当前所在的类的，
    就是这个空间的所在的页面调用 this.lbTakeCount.string = i18n("balance.你完成了%{value}个订单", { value: take});
    传入动态的实际参数，然后在这个lable上就不需要在去挂载 LocalizedLabel类

    5、图片多语言 直接挂载LocalizedSprite类 到对应的sprite节点上去
    然后根据languages.length的列表填入如 “en” 然后拖入英文的图片，然后“zh” 拖入中文的图片
 */

class i18nCls extends Singleton{
    public  inst: any = null;
    //多语言数组
    public languages: {
            en: object;
            zh: object;
        } = { en: {}, zh: {} };
    //当前语言 默认语言中文
    public get curLang(): any {
        return localStorage.getItem(langCacheKey) ?? curLang;
    }
    //设置当前语言并更新到 localStorage
    public set curLang(language: any) {
        let cur = this.curLang;
        if (cur !== language) {
            //将语言存储到localStorage
            localStorage.setItem(langCacheKey, language);
            //初始化语言
            this.init(language);
        }
    }

    constructor() {
        super();
        this.init();
    }

    public initPolyglot (data: any) {
        if (data) {
            if (this.inst) {
                this.inst.replace(data);
            } else {
                this.inst = new Polyglot({ phrases: data, allowMissing: true });
            }
        }
    }

    /**
     * 当前语言是否是中文
     */
    public get isZh(): boolean {
        return this.curLang === "zh";
    }
    
    /**
     * This method allow you to switch language during runtime, language argument should be the same as your data file name
     * such as when language is 'zh', it will load your 'zh.js' data source.
     * @method init
     * @param language - the language specific data file name, such as 'zh' to load 'zh.js'
     */
    public init(language?: string){
        if (!language || language === this.curLang) {
            return;
        }
        let data = this.languages[language] || {};
        this.curLang = language;
        this.initPolyglot(data);
    }

    /**
     * this method takes a text key as input, and return the localized string
     * Please read https://github.com/airbnb/polyglot.js for details
     * @method t
     * @return {String} localized string
     * @example
     *
     * var myText = i18n.t('MY_TEXT_KEY');
     *
     * // if your data source is defined as
     * // {"hello_name": "Hello, %{name}"}
     * // you can use the following to interpolate the text
     * var greetingText = i18n.t('hello_name', {name: 'nantas'}); // Hello, nantas
     */
    public t (key: any, opt ?: object) {
        //检查数据是否加载
        if (!this.inst || Object.keys(this.inst.phrases).length === 0) {
            const data = this.languages[this.curLang] || {};
            this.initPolyglot(data);
        }
        //调用 Polyglot 的翻译方法
        return this.inst?.t(key, opt) || key;
    }

    /**
     * inst: polyInst
     * 是遍历场景中所有的 LocalizedLabel 和 LocalizedSprite 组件，并更新它们的显示内容
    */
    public updateSceneRenderers () { // very costly iterations
        let rootNodes = director.getScene()!.children;
        // walk all nodes with localize label and update
        let allLocalizedLabels: any[] = [];
        for (let i = 0; i < rootNodes.length; ++i) {
            let labels = rootNodes[i].getComponentsInChildren(LocalizedLabel);
            Array.prototype.push.apply(allLocalizedLabels, labels);
        }
        for (let i = 0; i < allLocalizedLabels.length; ++i) {
            let label = allLocalizedLabels[i];
            if(!label.node.active)continue;
            label.updateLabel();
        }
        //walk all nodes with localize sprite and update
        let allLocalizedSprites: any[] = [];
        for (let i = 0; i < rootNodes.length; ++i) {
            let sprites = rootNodes[i].getComponentsInChildren(LocalizedSprite);
            Array.prototype.push.apply(allLocalizedSprites, sprites);
        }
        for (let i = 0; i < allLocalizedSprites.length; ++i) {
            let sprite = allLocalizedSprites[i];
            if(!sprite.node.active)continue;
            sprite.updateSprite(this.curLang);
        }
    }
};

const instance = i18nCls.ins();
//使用函数保持this 绑定
const i18nFn = (key: any, opt?: object) => instance.t(key, opt);
//拷贝所有方法到函数对象
const i18n = Object.setPrototypeOf(i18nFn, instance);
//导出类型声明保持不变
export default i18n as typeof instance & ((key: any, opt?: object) => string);