import { _decorator, Component, director,Node, Vec3, Widget} from 'cc';
import { Singleton } from './Singleton';
import { Constants } from '../../data/Constants';
import { Utils } from '../../utils/Utils';
import { ResUtil } from '../../utils/ResUtil';

const { ccclass, property } = _decorator;

interface PageActive{
    show: () => {},
    hide: () => {},
    back: () => {},
}

@ccclass("uiManager")
export class uiManager extends Singleton {
    //tabbar pages主页面节点放在这个容器中
    private pageUIs: string = 'pageUIs';
    //pop dialog出来的节点放在这个容器中
    private popUIs: string = 'popUIs';
    //页面缓存
    public panels = new Map <string, Node>();

    /**
    * 展示场景
    * @param sceneName 场景名字
    * @param delay 延迟的时间
    */
    public showScene(sceneName: string, delay: number = 0.1): void {
        if (delay) {
            setTimeout(() => {
                director.loadScene(sceneName);
            }, delay * 1000);
        } else {
            director.loadScene(sceneName);
        }
    }

    /**
     * 展示一个resources资源包里的节点
     * @param path Prefab的路径名称
     * @param args 给组建传递的参数
     * @param cb 展示完成的回调函数
     * @returns 
     */
    public async show(path: string, args?: any, cb?: Function): Promise<Node>{
        const pageName: string = path.split('/').pop();
        if (!args) {args = [];}
        const scriptName = pageName.replace(/^\w/, (c) => c.toUpperCase());
        let panel: any = this.panels.get(path);
        if(!panel){
            panel = await ResUtil.loadRes(path);
            this.panels.set(path, panel);
        }
        if (!panel || !(panel instanceof Node)) return;
        //动态添加页面的路径path信息，在关闭和销毁的时候用到
        panel['_uiPath'] = path;
        let isMain = Object.values(Constants.mainUIs).includes(path);
        const name: string = isMain ? this.pageUIs : this.popUIs;
        let parent:Node = this.getCurentSceneRoot();
        parent = Utils.findName(parent,name) ?? parent;
        panel.parent = parent;
        panel.active = true;
        panel.getComponent(Widget)?.updateAlignment();
        if(isMain){
            parent.children.forEach((e:Node) => {
                e.setPosition(new Vec3(e.name == pageName ? 0 : 500000,0,1));
            });
        }else{
            panel.setSiblingIndex(parent.children.length);
        }
        const comp = panel.getComponent(scriptName);
        if (comp && (comp as Component & PageActive)['show']){
            (comp as Component & PageActive)['show'].apply(comp, args);
        }
        if(typeof cb === 'function') {cb?.(panel)};
    }

    /**
     * 根据堆栈页面顺序返回到某一个页面
     * @param path 返回某一个界面
     * @param args 返回的附带参数
     * @param cb 回调
     * @returns 
     */
    public pop(path?: string,args?: any,cb?: Function){
        let canvas:Node = this.getCurentSceneRoot();
        let popUIs:Node = Utils.findName(canvas,this.popUIs);
        let isMain:boolean = Object.values(Constants.mainUIs).includes(path);
        let comp:any = null;
        if(Utils.isNull(path)){
            if(popUIs.children.length > 0){//关闭存在的popUIs最后一个节点
               let node: Node = popUIs.children.slice(-2)[0];
               node.parent = null;
               const scriptName = node.name.replace(/^\w/, (c) => c.toUpperCase());
               comp = node.getComponent(scriptName);
            }else{//返回主页面的上一层节点
               comp = this.getPageComponent(Constants.mainUIs.main);
               comp.tabBarIndex = comp.preIndexs.slice(-2)[0];
            }
        }else{
            const pageName: string = path.split('/').pop();
            const scriptName = pageName.replace(/^\w/, (c) => c.toUpperCase());
            if (!args) {args = [];}
            if(isMain){
                comp = this.getPageComponent(Constants.mainUIs.main);
                comp.tabBarIndex = comp.sceneNames.indexOf(path);
                popUIs.removeAllChildren();
            }else{
                let panel: Node = this.panels.get(path);
                let targetIndex = popUIs.children.findIndex(n => n.name == pageName);
                if (targetIndex !== -1) {
                    popUIs.children.slice(targetIndex + 1).forEach(n => {
                        n.parent = null;
                    });
                    popUIs.children.splice(targetIndex + 1);
                }
                panel.setSiblingIndex(panel.parent.children.length);
                comp = panel.getComponent(scriptName);
            }
        }
        if(comp && (comp as Component & PageActive)['pop']){
           (comp as Component & PageActive)['pop'].apply(comp, args);
        }
        if(typeof cb === 'function') {cb?.()};
    }

    /**
     * 直接关闭固定的名字中的一个页面
     * @param path Prefab的路径名称
     * @param cb 展示完成的回调函数
     * @returns 
     */
    public hide(path: string,cb?: Function){
        if(!this.panels.has(path))return;
        let panel: Node = this.panels.get(path);
        const pageName: string = path.split('/').pop();
        const scriptName = pageName.replace(/^\w/, (c) => c.toUpperCase());
        let isMain = Object.values(Constants.mainUIs).includes(path);
        if(isMain){
            let container = Utils.findName(this.getCurentSceneRoot(),this.pageUIs);
            container.children.forEach((e:Node) => {
                e.setPosition(new Vec3((e.name == pageName ? 500000 : 0),0,1));
            });
        }else{
            panel.parent = null;
            const comp = panel.getComponent(scriptName);
            if(comp && (comp as Component & PageActive)['hide']){
              (comp as Component & PageActive)['hide'].apply(comp);
            }
        }
        if(typeof cb === 'function') {cb?.()};
    }

    /**
     * 从缓存页面中获取一个脚本
     * @param path 缓存的路径
     * @param scriptName 不传默认获取path名字最后一个字符串作为脚本的名字
     * @returns 
     */
    public getPageComponent(path: string,scriptName?:string): any{
        if(!this.panels.has(path)){
           return null;
        }else{
            const sName = path.split('/').pop().replace(/^\w/, (c) => c.toUpperCase());
            let node: Node = this.panels.get(path);
            return node.getComponent(scriptName ?? sName);
        }
    }

    /**
     *从缓存页面中获取一个页面
     * @param path 缓存的路径
     */
     public getPageNode(path: string): Node{
        if(Utils.isNull(path))return null;
        if(!this.panels.has(path))return null;
        return this.panels.get(path);
    }

    /**
     * 在界面中显示的节点是否存在
     */
    public hasPageNode(path: string): boolean{
        if(Utils.isNull(path))return false;
        let name = path.split('/').pop();
        let canvas:Node = this.getCurentSceneRoot();
        let pages = Utils.findName(canvas,this.pageUIs);
        let popUIs = Utils.findName(canvas,this.popUIs);
        let nodes = pages.children.concat(popUIs.children)
        return nodes.some(e=>e.name == name);
    }

    /**
     * 得到当前场景的节点的根节点
     * @returns 根结点
     */
    public getCurentSceneRoot(): Node {
        return director.getScene().getChildByName('Canvas');
    }
}

//全局单例
export const uiMgr = uiManager.ins();
