import { Constructor, director, error, find, instantiate, Node, Prefab, resources, Scene } from "cc";
import { UIBase, UIType } from "../Game/GameFrameWork/UIBase";

class UIManager {
    static instance: UIManager = null;
    private _uis: Map<string, UIBase> = new Map();
    private _uiNodes: Map<string, Node> = new Map();
    private _prefabs: Map<string, Prefab> = new Map();
    
    //获取UI
    getUI<T extends UIBase>(name: string | Constructor<T>): T {
        if (typeof (name) === "string") {
            return <T>this._uis.get(name);
        }
        //遍历所有的value组成的数组
        for (const ui of Array.from(this._uis.values())) {
            if (ui instanceof name) {
                return <T>ui;
            }
        }
        return null;
    }

    //打开页面 全屏 弹窗 挂件
    async openUI(preName: string, type: UIType = UIType.PAGE) {

        let ui = this._uis.get(preName);
        if (ui) {
            //把ui显示出来
            ui.show();
            return;
        }
        //是否在节点容器当中
        let node = this._uiNodes.get(preName);
        if (node) {
            node.active = true;
            return;
        }
        //node 不存在的情况下 加载出来
        //先判断一下预制体是否下载过
        let prefab = this._prefabs.get(preName);
        if (!prefab) {
            prefab = await this._loadUI("UI/" + preName);
            this._prefabs.set(preName, prefab)
        }

        //查找ui根节点
        node = instantiate(prefab);
        let root = find("Canvas/UIRoot");
        if(!root){
            //如果场景当中没有 就加载预制体 创建一个
            const rootPre: Prefab = await this._loadUI("UI/UIRoot")
            root = instantiate(rootPre);
            root.parent = find("Canvas");
        }
        node.parent = root.children[type];

        //处理逻辑
        ui = node.getComponent(UIBase);
        if (ui) {
            //对ui进行多态处理
            ui.init();
            ui.UIName = preName;
            this._uis.set(preName, ui);
            return;
        }
        this._uiNodes.set(preName, node);
        // resources.load("UI/" + preName, Prefab, (err: Error, asset: Prefab)=>{
        //     const node = instantiate(asset);
        //     node.parent = find("Canvas/UIRoot").children[type];
        //     //处理逻辑
        //     const ui = node.getComponent(UIBase);
        //     //对UI进行多态处理

        // })
    }

    async openScene(sceneName: string, uiName?: string){
        await this._loadScene(sceneName);
        uiName && this.openUI(uiName);
    }

    private _loadScene(sceneName: string){
        new Promise((revolve, reject)=>{
            director.loadScene(sceneName,(err: Error, scene: Scene)=>{
                if(err){
                    error("加载" + sceneName + "场景错误！");
                    reject(err);
                }
                else{
                    revolve(scene);
                }
            })
        })
    }

    //加载UI预制体
    private _loadUI(path: string): Promise<Prefab> {
        return new Promise((revole, reject) => {
            resources.load(path, Prefab, (err: Error, asset: Prefab) => {
                if (err) {
                    reject(err);
                } else {
                    revole(asset);
                }
            })
        })
    }

    //关闭UI
    closeUI(uibase: string | UIBase, clear: boolean = true){
        let ui: UIBase;
        if(typeof(uibase) === "string"){
            ui = this._uis.get(uibase);
            if(ui){
                ui.hide(clear);
                clear && this._uis.delete(uibase);
            }
            return;
        }
    
        uibase.hide(clear);
        clear && this._uis.delete(uibase.UIName);
        return;
        // for(const u of Array.from(this._uis.values())){
        //     if(uiName === u){
        //         u.hide(clear);
        //         return;
        //     }
        // }
    }

    //UI之间的消息互通
    sendMsg(msg: string,ui: string|UIBase, ...args){
        let m: UIBase;
        if(typeof(ui) === "string"){
            m = this.getUI(ui);
        }
        else{
            m = ui;
        }
        //判断如果找到的UI模块是个空 什么也不做
        if(!m){
            return;
        }

        //m 是个对象 找m中有没有 名字叫做msg的函数
        //对象都是键值对 访问键对应的值
        const func = m[msg];
        if(func && typeof(func) === "function"){
            func.apply(m, [...args]);
            return;
        }
    }
}

export const UIMgr: UIManager = UIManager.instance = new UIManager();
