import { Prefab, Node, instantiate, isValid } from "cc";
import { UIHelper } from "../common/UIHelper";
import { resLoader } from "../res/ResLoader";
import { NodeEx } from "./NodeEx";
import { NodePool } from "./NodePool";


export class NodePoolEx {
    private _pools = new Map<number | string, NodePool>();
    private _ready: boolean = false;                //节点是否初始化完毕
    private _size: number = 10;                     //池大小
    private _res: Prefab = null;                    //预制
    private _clear_time: number = 120;              //清理时间(秒)

    /**
     * 初始化节点池
     * @param bundle 包名
     * @param url 路径
     * @param size 节点池大小
     * @param clear 节点池清理时间(秒)
     * @param calback 初始化成功回调
     */
    init(bundle: string, url: string, size: number = 10, clear: number = 120, calback: Function) {
        this._pools.clear();
        if(this._res){
            this._size = size;
            this._clear_time = clear;
            this._ready = true;
            calback && calback();
        }
        else {
            resLoader.load(bundle, url, Prefab, (error: Error, prefab: Prefab) => {
                if (error) {
                    console.error(error);
                } else {
                    this._res = prefab;
                    this._res.addRef();
                    this._size = size;
                    this._clear_time = clear;
                    this._ready = true;
                    calback && calback();
                }
            });
        }
    }

    /**
     * 获取节点
     * @param id 节点标识
     * @param parent 父节点
     * @param val 自定义参数
     */
    getNode(id: number | string, parent: Node = null, ...val: any[]) {
        if (this._ready) {
            let pool = this._pools.get(id);
            if (!pool) {
                pool = new NodePool();
                pool.init(this._res, this._size, this._clear_time, true);
                this._pools.set(id, pool);
            }
            let template = pool.getNode(parent);
            if (template) {
                template.node_id = id;
                template.reuse(...val);
                return template;
            }
        }
        return null;
    }

    putNode(template: NodeEx) {
        if (template && template.isValid) {
            let pool = this._pools.get(template.node_id);
            if (pool) {
                pool.putNode(template);
            } else {
                template.node.destroy();
            }
        }
    }

    clear() {
        this._pools.forEach((pool, key) => {
            pool.clear();
        });
        (this._res) && this._res.decRef();
        this._res = null;
    }
}