

import { RedDotTip } from "./RedDotTip";

/**
 * 红点节点
 */
class RedNode {

    public tail: RedNode;

    public nextNode: RedNode;

    public ui: UI.Widget;
    public redDotUi: RedDotTip;

    /** 获取 UI的显示状态*/
    public getUIRedDotState: (ui: UI.Widget) => boolean;
    public setShowUIRedDot: (ui: UI.Widget) => boolean;

    /** 红点节点对象池 */
    public getRedDotUICall: () => RedDotTip;
    public releaseRedDotUICall: (ui) => void;

    private z: number = 0;

    private isVisible: boolean = false;

    /**
     * 查询是否显示
     * @param ui 
     * @returns 
     */
    private findIsVisible(ui: UI.Widget) {

        if (ui.parent != null) {

            if (ui.visible == false) {
                this.isVisible = false;
                return;
            } else {
                this.isVisible = true;
                this.findIsVisible(ui.parent);
            }

        }

    }

    /**
     * 查询zOrder
     * @param ui 
     */
    private findZ(ui: UI.Widget) {

        if (ui.parent != null) {

            if (this.z < ui.zOrder) {
                this.z = ui.zOrder;
            }

            this.findZ(ui.parent);

        }


    }

    /**
     * 隐藏
     * @returns 
     */
    public hide() {

        if (this.redDotUi == null) {
            return
        }

        this.releaseRedDotUICall(this.redDotUi);
        this.redDotUi = null;

        return

    }

    /**
     * 刷新
     * @returns 
     */
    public refresh() {

        /** 当前红点已经显示 */
        if (this.getUIRedDotState(this.ui)) {
            if (this.redDotUi == null) {
                return
            }
            this.releaseRedDotUICall(this.redDotUi);
            this.redDotUi = null;
            return;
        }

        this.findIsVisible(this.ui);

        if (!this.isVisible) {

            if (this.redDotUi == null) {
                return
            }

            this.releaseRedDotUICall(this.redDotUi);
            this.redDotUi = null;

            return

        }

        this.findZ(this.ui)

        this.setShowUIRedDot(this.ui);

        if (this.redDotUi == null) {
            this.redDotUi = this.getRedDotUICall();
        }

        let pos2 = Vector.zero;
        let pos = Vector.zero;
        UI.localToViewport(this.ui.tickSpaceGeometry, Vector2.zero, pos2, pos);

        UI.UIManager.instance.showUI(this.redDotUi, 0, pos);
        this.redDotUi.uiObject.zOrder = this.z + 1;


    }

}

export class RedDotUtil {

    static _instance: RedDotUtil;

    static get instance() {
        if (RedDotUtil._instance == null) {
            RedDotUtil._instance = new RedDotUtil();
        }
        return RedDotUtil._instance;
    }

    private trees: Map<string, RedNode> = new Map<string, RedNode>();

    private triggerKey: Map<string, number> = new Map<string, number>();

    private redPool = [];

    private showList: Map<string, RedNode> = new Map<string, RedNode>();

    private removeList: Map<string, RedNode> = new Map<string, RedNode>();

    private uiRedDotState: Map<UI.Widget, boolean> = new Map<UI.Widget, boolean>();

    private setUIShowRedDot(ui: UI.Widget) {

        this.uiRedDotState.set(ui, true);

    }

    private getUIShowRedDot(ui: UI.Widget): boolean {
        if (!this.uiRedDotState.has(ui)) return false;

        return this.uiRedDotState.get(ui);
    }

    private pushRedDotTip(tip: RedDotTip) {
        UI.UIManager.instance.hideUI(tip);
        this.redPool.push(tip);
    }

    /**
     * 获取红点提示UI
     * @returns 
     */
    private getRedDotTip(): RedDotTip {

        if (this.redPool.length > 0) {
            return this.redPool.shift();
        }

        let redUI = UI.UIManager.instance.create(RedDotTip);
        return redUI;
    }

    /**
     * 创建一个节点
     * @param redKey 
     * @param ui 
     * @returns 
     */
    private newNode(redKey: string, ui: UI.Widget): RedNode {

        let node = new RedNode();
        node.ui = ui;
        node.getRedDotUICall = this.getRedDotTip.bind(this);
        node.releaseRedDotUICall = this.pushRedDotTip.bind(this);
        node.getUIRedDotState = this.getUIShowRedDot.bind(this);
        node.setShowUIRedDot = this.setUIShowRedDot.bind(this);
        return node;

    }

    /**
     * 触发一个红点数事件
     * @param eventName 
     * @returns 
     */
    public triggerRedDotEvent(eventName: string) {
        if (!this.trees.has(eventName)) {
            return;
        }

        //console.error("触发事件" + eventName);
        let tree: RedNode = this.trees.get(eventName);

        this.showList.set(eventName, tree);
    }

    /**
     * 移除一个红点事件
     * @param eventName 
     */
    public removeRedDotEvent(eventName: string) {

        if (this.showList.has(eventName)) {
            this.hideRedDotEvent(eventName);
        }

        if (this.trees.has(eventName)) {
            this.trees.delete(eventName);
        }

    }

    /**
     * 隐藏一个红点事件
     */
    public hideRedDotEvent(eventName: string) {

        if (this.showList.has(eventName)) {
            this.removeList.set(eventName, this.showList.get(eventName));
            this.showList.delete(eventName);
        }

    }


    /**
     * 根据红点数事件获取对应UI
     * @param eventName 
     * @returns 
     */
    public getRedDotUIArrsByEventName(eventName: string): Array<UI.Widget> {

        if (!this.trees.has(eventName)) {
            return [];
        }

        let tree: RedNode = this.trees.get(eventName);

        let uiArrs = [];

        do {

            uiArrs.push(tree.ui);
            tree = tree.nextNode;

        } while (tree != null);

        return uiArrs;

    }

    /**
     * 根据老的红点树，扩容一颗新的树
     * @param srcEventName 
     * @param newEventName 
     * @param uiArrays 
     * @returns 
     */
    public addRedDotPathByEvt(srcEventName: string, newEventName: string, ...uiArrays: Array<UI.Widget>): RedDotUtil {

        if (!this.trees.has(srcEventName)) {
            return this;
        }

        if (this.trees.has(newEventName)) {
            return this;
        }

        let tree = this.trees.get(srcEventName);

        let oldUI = [];
        do {

            oldUI.push(tree.ui);
            tree = tree.nextNode;

        } while (tree != null);

        oldUI = oldUI.concat(uiArrays);

        this.addRedDotPath(newEventName, ...oldUI);

    }

    /**
     * 添加一颗红点树
     * @param eventName 
     * @param uiArrays 
     * @returns 
     */
    public addRedDotPath(eventName: string, ...uiArrays: Array<UI.Widget>): RedDotUtil {

        if (uiArrays.length <= 0) return this;

        let tree: RedNode;

        if (this.trees.has(eventName)) {
            return this;
        } else {
            tree = this.newNode(eventName, uiArrays[0]);
        }

        let head = tree;
        let curNode = tree;

        for (var i = 1; i < uiArrays.length; i++) {

            let node = this.newNode(eventName, uiArrays[i]);

            curNode.nextNode = node;
            curNode = node;
        }

        head.tail = curNode;

        this.trees.set(eventName, head);

        return this;

    }

    public onUpdate(dt: number): void {
        this.uiRedDotState.forEach((v, k) => {
            this.uiRedDotState.set(k, false);
        })

        this.removeList.forEach((v, k) => {

            let temp = v;
            do {
                temp.hide();
                temp = temp.nextNode;
            } while (temp != null);

        })
        this.removeList.clear();

        this.showList.forEach((v, k) => {

            let temp = v;
            do {
                temp.refresh();
                temp = temp.nextNode;
            } while (temp != null);

        })

    }


}