import { Animation, Canvas, find, instantiate, Node, Prefab, Sprite, Widget } from 'cc';
import { PREVIEW } from 'cc/env';
import { FrameworkConf } from '../config/FrameworkConf';
import { EventMgr } from '../event/EventManager';
import { resLoader } from '../res/ResLoader';
import { StringUtil } from '../util/StringUtil';
import { TimeUtil } from '../util/TimeUtil';
import { BaseView, UIShowType } from './BaseView';
import { LayerConf, LayerInfo } from './LayerManager';
import { UserData } from '../../game/data/UserData';
import { Layer_Conf, ViewID } from '../config/LayerConf';

export class BaseLayer extends Node {
    private _layer_queue: LayerInfo[] = [];                       //UI队列
    private _layer_conf: { [key: number]: LayerConf } = {};       //UI配置
    private _layer_opening: boolean = false;                      //是否正在打开UI
    private _layer_cache: LayerInfo[] = [];                       //UI缓存
    private _layer_manage = false;                                //是否启用层级管理
    private _bottom_layer = 0;                                    //底层UI数量(通常位于UI栈底部,不受UI切换影响)

    constructor(name: string, conf: any, manage: boolean = false) {
        super(name);
        this._layer_conf = conf;
        let widget = this.addComponent(Widget);
        widget.isAlignLeft = widget.isAlignRight = widget.isAlignTop = widget.isAlignBottom = true;
        widget.left = widget.right = widget.top = widget.bottom = 0;
        widget.alignMode = 2;
        widget.enabled = true;
        this._layer_queue = [];
        this._layer_cache = [];
        this._layer_opening = false;
        this._layer_manage = manage;
    }

    /**
     * 打开UI
     * @param id UIID
     * @param args 打开UI的可传参数
     * @param callback UI打开成功过后的回调
     */
    open(id: number, callback: Function = null, args: any[]) {
        let conf = this._layer_conf[id];
        if (conf) {
            let info: LayerInfo = {
                id: id,
                args: args,
                view: null,
                res: null,
                callback: callback,
                active: true,
                bLoading: true
            };
            if (this._layer_opening) {
                //队列里不能有相同的UI
                for (let ui of this._layer_queue) {
                    if (ui.id === id) {
                        return false;
                    }
                }
                //插入待打开队列
                this._layer_queue.push(info);
                return false;
            }
            //开同一UI 则刷新
            let curView = this.getUIView(id);
            if (curView) {
                //let conf = this._layer_conf[id];
                if (conf.reset) {
                    console.log("页面存在,直接刷新")
                    //传递自定义参数
                    curView.onOpen(...info.args);
                    //回调
                    info.callback && info.callback();
                    return true
                }
                else {
                    console.log("页面存在,不刷新")
                    return false;
                }

            }

            this._layer_opening = true;

            this._layer_cache.push(info);

            let __time = TimeUtil.getTime();

            let self = this
            /**
             * 加载失败
             * @param bRes 资源已加载 
             */
            let funError = function (bRes) {

                if (bRes) {
                    resLoader.release(conf.url, conf.bundle);
                }
                for (let i = self._layer_cache.length - 1; i >= 0; --i) {
                    if (self._layer_cache[i] == info) {
                        self._layer_cache.splice(i, 1);
                        break;
                    }
                }
                //处理待打开队列中的UI
                self._layer_opening = false;
                self._open_next();
            }

            //加载资源
            resLoader.load(conf.bundle, conf.url, Prefab, (error: Error, prefab: Prefab) => {
                if (error) {
                    console.error("载入资源失败:" + conf.url);
                    funError(false)
                    return false
                } else {
                    if (!info.bLoading) {
                        console.error("资源已不需要了:" + conf.url);
                        funError(true)

                        return false
                    }
                    info.bLoading = false;
                    (!conf.cache) && (info.res = prefab);
                    let node = instantiate(prefab);
                    node.active = true;
                    console.log(`复制预制体:${conf.url}`)

                    if (!node) {
                        console.error("初始化Node失败");
                        funError(true)
                        return false;
                    }
                    let view = node.getComponent(BaseView);
                    if (!view) {
                        console.error("UI未找到UIView组件");
                        funError(true)
                        return false;
                    }
                    prefab.addRef();
                    view.enabled = true;
                    info.view = view;
                    view.view_id = id;
                    this.addChild(node);
                    //统计底层UI数量
                    (conf.bottom) && ++this._bottom_layer;

                    this._play_anim(id, node, "open", () => {
                        //刷新UI
                        this._updateUI();
                        //传递自定义参数
                        view.onOpen(...info.args);
                        //发送打开事件

                        EventMgr.fireEvent(FrameworkConf.Event.OPEND_UI, info.id);
                        //回调
                        info.callback && info.callback();
                        //处理待打开队列中的UI
                        this._layer_opening = false;
                        this._open_next();
                    });
                    (PREVIEW) && console.log(StringUtil.format("UI[{0}]加载耗时:{1}毫秒", ViewID[info.id], TimeUtil.getTime() - __time));
                }
            });
            return true;
        }
        return false;
    }

    private _open_next() {

        let info = this._layer_queue.shift();
        info && this.open(info.id, info.callback, info.args);
    }

    private _play_anim(id: number, node: Node, name: string, callback: Function,) {
        //是否播放动画
        let conf = this._layer_conf[id];
        if (conf.anim) {
            let anim = node.getComponent(Animation);
            if (anim) {
                anim.on(Animation.EventType.FINISHED, () => {
                    callback && callback();
                    callback = null;
                }, this);
                let animName = "";
                if (conf.anim == 1) {
                    animName = "ui_" + name;
                } else if (conf.anim == 2) {
                    animName = "tips_" + name;
                }
                anim.play(animName);
                return;
            }
            else{
                console.error("ui:" + id + "缺少Animation组件");
                callback && callback();
            }
        } else {
            callback && callback();
            callback = null;
        }
    }

    private _updateUI() {
        if (this._layer_manage) {
            let show_idx = this._layer_cache.length - 1, hide_idx = 0;;
            for (; show_idx >= 0; --show_idx) {
                if (this._layer_cache[show_idx].active) {
                    this._layer_cache[show_idx].view?.onShow();
                    let mode = this._layer_cache[show_idx].view?.show_type;
                    if (mode == UIShowType.Single) {
                        for (let i = 0; i < this._bottom_layer; ++i) {
                            this._layer_cache[i] && this._layer_cache[i].view?.onShow();

                        }
                        hide_idx = this._bottom_layer;
                        break;
                    } else if (mode == UIShowType.FullScreen) {
                        break;
                    }
                }
            }
            for (let i = hide_idx; i < show_idx; ++i) {
                this._layer_cache[i].view?.onHide();
            }
            let find = false;
            for (let cache of this._layer_cache) {
                if (cache.active) {
                    if (cache.view?.show_type == UIShowType.FullScreen) {
                        find = true;
                        //如果有全屏隐藏底层UI
                        for (let i = 0; i < this._bottom_layer; ++i) {
                            this._layer_cache[i] && this._layer_cache[i].view?.onHide();
                        }
                        break;
                    }
                }

            }
            EventMgr.fireEvent("_Framewrok_Show_GameLayer", !find);
        }
    }

    /**
    * 关闭UI
    * @param ui 该值可为UIID也可为this
    */
    close(ui: number | BaseView) {
        let view = (typeof ui === "number") ? this.getUIView(ui) : ui;
        if (view) {
            let info: LayerInfo = null;
            for (let i = 0; i < this._layer_cache.length; ++i) {
                info = this._layer_cache[i];
                if (info.view == view) {
                    this._layer_cache.splice(i, 1);
                    //刷新UI
                    let pre_info = (this._layer_cache.length >= 1) ? this._layer_cache[this._layer_cache.length - 1] : null;
                    if (pre_info) {
                        if (!pre_info.active) {
                            pre_info = (this._layer_cache.length >= 2) ? this._layer_cache[this._layer_cache.length - 2] : null;
                        }
                    }
                    this._updateUI();

                    this._play_anim(info.view.view_id, info.view.node, "close", () => {
                        //显示最后一个UI
                        if (pre_info && pre_info.view) {
                            pre_info.view.onShow();
                        }
                        this._clearUI(info);
                    });
                    break;
                }
            }
        }
        else {
            let info: LayerInfo = null;
            for (let i = 0; i < this._layer_cache.length; ++i) {
                info = this._layer_cache[i];
                if (info.id == ui) {
                    info.bLoading = false;
                    console.log("closeUI with out view:", info.id);
                }
            }
        }
    }
    ShowUI(UI, state, callback: Function = null, args: any[]) {
        let nohave = true;
        let exist = []
        for (let i in this._layer_cache) {
            if (this._layer_cache[i].id === UI) {
                nohave = false
                if (this._layer_cache[i] && this._layer_cache[i].view) {
                    if (state) {
                        for (let existUI of exist) {
                            existUI.view.onHide();
                        }
                        this._layer_cache[i].view.onShow();
                        this._layer_cache[i].active = true;
                    } else {
                        for (let existUI of exist) {
                            existUI.view.onShow();
                        }
                        this._layer_cache[i].view.onHide();
                        this._layer_cache[i].active = false;
                    }
                    callback && callback();
                }
                return;
            }
            exist.push(this._layer_cache[i])
        }
        if (nohave) {
            this.open(UI, callback, args);
        }
    }
    /**
     * 获取UI对应的UIView
     * @param id UIID
     */
    getUIView(id: number) {
        for (let ui of this._layer_cache) {
            if (ui.id === id) {
                if (ui.active) {
                    return ui.view;
                }
            }
        }
        return null;
    }

    /**
     * 关闭当前层的所有UI
     */
    closeAll(withoutID: number = -1) {

        for (let index = this._layer_cache.length - 1; index >= 0; index--) {
            let info = this._layer_cache[index];
            if (info.id !== withoutID) {
                this.close(info.id);
                let conf = this._layer_conf[info.id];
                (!conf.special) && this._clearUI(info);
            }

        }
        this._layer_queue = [];
    }

    private _clearUI(info: LayerInfo) {
        if (info && info.view) {
            let conf = this._layer_conf[info.id];
            (conf && conf.bottom) && --this._bottom_layer;
            info.view.onClose();
            //发送打开事件
            EventMgr.fireEvent(FrameworkConf.Event.CLOSE_UI, info.id);
            info.view.unscheduleAllCallbacks();
            info.view.node.removeFromParent();
            info.view.release();
            EventMgr.removeEvent(info.view);
            info.view.node.destroyAllChildren();
            info.view.node.destroy();
            info.res && (info.res.decRef());
            info.res = null;
            info.view = null;
            info = null;
        }
    }

    showLayerUI(show: boolean) {
        for (let cache of this._layer_cache) {
            if (show) {
                cache.active && cache.view?.onShow();
            } else {
                cache.view?.onHide();
            }
        }
    }
}