import { _decorator, Component, instantiate, isValid, Node, Prefab } from 'cc'
import { Debug } from '../util/Debug'
import { UIType } from '../enum/UIType'
import { EventMgr } from './EventMgr'
import { EventType } from '../enum/EventType'
import { ResMgr } from './ResMgr'
import { UIBase } from '../scriptBase/UIBase'
import { Bundle } from '../enum/Bundle'
import { DtoUI } from '../dto/DtoUI'
const { ccclass, property } = _decorator

const Tag: string = 'zh:UIMgr'

@ccclass('Manager/UIMgr')
export class UIMgr extends Component {

    private static _inst: UIMgr = null
    private static _node: Node = null

    @property(Node)
    private popUpMask: Node = null

    private static _openedUI: Object = {}
    private static _popUpStack: string[] = []
    private static _toast: Node = null

    protected onLoad(): void {
        globalThis.UIMgr = UIMgr
        UIMgr._inst = this
        UIMgr._node = this.node
        UIMgr.init()
    }

    private static init(): void {
        EventMgr.on(EventType.OpenUI, this.open, this)
        EventMgr.on(EventType.CloseUI, this.close, this)
    }

    public static async open(uiName: string, data?: unknown, dtoUI?: DtoUI) {
        if (this.isOpened(uiName)) {
            Debug.Warn(Tag, `${uiName}已经打开`)
            return
        }
        let uiBundle: Bundle = dtoUI?.uiBundle ?? Bundle.UI
        let isUILoaded: boolean = ResMgr.isLoaded(uiBundle, uiName)
        if (!isUILoaded) {
            await ResMgr.loadRes(uiBundle, uiName)
        }
        let uiPrefab: Prefab = ResMgr.getRes(uiBundle, uiName)
        if (!uiPrefab) {
            Debug.Error(Tag, `${uiName}不存在`)
            return
        }

        let uiNode: Node = instantiate(uiPrefab)
        let ui: UIBase = uiNode.getComponent(UIBase)
        Debug.Log(Tag, `打开${uiName}`)

        let uiType: UIType = dtoUI?.uiType ?? ui.uiType
        let uiParent: Node = this._node.children[uiType]
        uiParent.addChild(uiNode)
        ui.onOpen(data)

        if (uiType === UIType.PopUp) {
            let idx: number = uiNode.getSiblingIndex()
            this._inst.popUpMask.active = true
            this._inst.popUpMask.setSiblingIndex(idx - 1)
            this._popUpStack.push(uiName)
        }
        if (uiType === UIType.Toast) {
            isValid(this._toast) && this._toast.destroy()
            this._toast = uiNode
        } else {
            this._openedUI[uiName] = ui
        }
    }

    public static close(uiName: string, data?: unknown): void {
        if (!this.isOpened(uiName)) return
        let ui: UIBase = this._openedUI[uiName]
        Debug.Log(Tag, `关闭${uiName}`)
        let uiType: UIType = ui.uiType
        if (uiType === UIType.PopUp) {
            let idx: number = this._popUpStack.indexOf(uiName)
            this._popUpStack.splice(idx, 1)
            if (this._popUpStack.length <= 0) {
                this._inst.popUpMask.active = false
            } else {
                let topWindowName: string = this._popUpStack[this._popUpStack.length - 1]
                let topWindow: UIBase = this._openedUI[topWindowName]
                let topWindowIdx: number = topWindow.node.getSiblingIndex()
                this._inst.popUpMask.setSiblingIndex(Math.max(0, topWindowIdx))
            }
        }
        ui.onClose(data)
        delete this._openedUI[uiName]
        ui.node.destroy()
    }

    public static get(uiName: string): UIBase {
        return this._openedUI[uiName]
    }

    public static isOpened(uiName: string): boolean {
        return this._openedUI.hasOwnProperty(uiName)
    }

}

