import { Prefab, Node, instantiate } from "cc";
import { UIHelper } from "../common/UIHelper";
import { Framework } from "../Framework";
import { resLoader } from "../res/ResLoader";
import { TimeUtil } from "../util/TimeUtil";
import { NodeEx } from "./NodeEx";

//一维节点池支持Prefab和Node模式

export class NodePool {
    private _ready: boolean = false;                //节点是否初始化完毕
    private _size: number = 10;                     //池大小
    private _res: Prefab | Node = null;             //资源
    private _pool: Node[] = [];                     //节点列表
    private _clear_time: number = 120;              //清理时间(秒)
    private _timer = -1;                            //定时器uuid
    private _reinforce = false;                     //是否是二维池

    /**
     * 初始化节点池
     * @param bundle 包名
     * @param url 路径
     * @param size 节点池大小
     * @param clear 节点池清理时间(秒)
     * @param calback 初始化成功回调
     * @param reinforce 是否是二维节点池
     */
    init(res: Prefab | Node, size: number, clear: number, reinforce?: boolean)
    init(bundle: string, url: string, size: number, clear: number, calback: Function, reinforce?: boolean)
    init() {
        if (this._pool.length > 0) {
            this.clear()
        }

        if(this._res && (this._res instanceof Prefab)){
            this._res.decRef();
            this._res = null;
        }
        this._pool = [];
        if (arguments) {
            if (arguments.length == 4) {
                this._ready = true;
                this._res = arguments[0];
                //如果res在Asset原型链上则引用计数+1
                if (this._res instanceof Prefab) {
                    this._res.addRef();
                }
                this._size = arguments[1];
                this._clear_time = arguments[2];
                if (this._clear_time > 0) {
                    this._timer = Framework.time.schedule(() => {
                        this._clearPool();
                    }, this._clear_time);
                }
                this._reinforce = arguments[3] ? arguments[3] : false;
            } else {
                this._size = arguments[2];
                this._clear_time = arguments[3];
                resLoader.load(arguments[0], arguments[1], Prefab, (error: Error, prefab: Prefab) => {
                    if (error) {
                        console.error(error);
                    } else {
                        this._res = prefab;
                        this._res.addRef();
                        this._ready = true;
                        arguments[4] && arguments[4]();
                        if (this._clear_time > 0) {
                            this._timer = Framework.time.schedule(() => {
                                this._clearPool();
                            }, this._clear_time);
                        }
                    }
                });
                this._reinforce = arguments[5] ? arguments[5] : false;
            }
        }
    }

    private _clearPool() {
        if (this._ready) {
            let cur_time = TimeUtil.getTimeEx(0);
            this._pool.forEach((node, idx) => {
                if (cur_time - node.getComponent(NodeEx).useTime >= this._clear_time) {
                    node.getComponent(NodeEx)?.unuse();
                    node.destroy();
                    this._pool.splice(idx, 1);
                }
            });
        }
    }

    /**
     * 设置节点池大小
     * @param size 大小
     */
    setPoolSize(size: number) {
        this._size = size;
    }

    /**
     * 获取节点
     * @param parent 父节点
     * @param val 自定义参数
     */
    getNode(parent: Node = null, ...val: any[]) {
        if (this._ready) {
            let node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node;
            if (!node.isValid) {
                while (true) {
                    node = ((this._pool.length > 0) ? this._pool.shift() : instantiate(this._res)) as Node;
                    if (node.isValid) {
                        break;
                    }
                }
            }
            node.active = true;
            if (parent) {
                UIHelper.setLayer(node, parent.layer);
                parent.addChild(node);
            }
            //如果是二维池则由二维池调用
            let template = node.getComponent(NodeEx);
            (!this._reinforce) && template.reuse(...val);
            return template;
        }
        return null;
    }

    /**
     * 归还节点,如果节点池已满将被销毁
     */
    putNode(template: NodeEx) {
        if (template && template.isValid) {
            template.unuse();
            if (this._pool.length >= this._size) {
                template.node.destroy();
            } else {
                template.node.removeFromParent();
                template.useTime = TimeUtil.getTimeEx(0);
                template.node.active = false;
                this._pool.push(template.node);
            }
        }
    }

    /**
     * 清理节点池
     */
    clear() {
        (this._timer != -1) && Framework.time.unschedule(this._timer);
        // for (let node of this._pool) {
        //     node.destroy();
        // }
        if (this._res) {
            // (this._res instanceof Prefab) ? this._res.decRef() : this._res.destroy();
            console.log("NodePool clear",(this._res && this._res.name));
           if(this._res instanceof Prefab) this._res.decRef() ;
            this._res = null;
        }
        this._pool = [];
        this._ready = false;
        (this._timer > 0) && Framework.time.unschedule(this._timer);
        this._timer = -1;
    }
}