const { ccclass, property } = cc._decorator;

@ccclass
export default class pool_manager {

    pools: any = {};
    resKey: any = {};

    init(callback, res: cc.Prefab) {
        // 初始化资源键值对
        this.initializeResKey(res);

        // 预创建并回收指定数量的节点到对象池
        this.preCreateAndRecoverNodes(res);

        // 执行回调函数（如果存在）
        this.executeCallback(callback);
    }

    // 初始化资源键值对的函数，将特定资源与对应的键关联起来
    private initializeResKey(res: cc.Prefab): void {
        this.resKey['TileBlock'] = res;
    }

    // 预创建并回收指定数量的节点到对象池的函数
    private preCreateAndRecoverNodes(res: cc.Prefab): void {
        for (let i = 0; i < 100; i++) {
            let node = cc.instantiate(res);
            this.recover('TileBlock', node);
        }
    }

    // 执行回调函数（如果存在）的函数
    private executeCallback(callback: () => void): void {
        callback && callback();
    }

    get(key: string) {
        // 获取指定键对应的节点池，如果不存在则创建一个新的节点池
        this.createNodePoolIfNotExists(key);

        // 尝试从节点池中获取节点，如果能获取到则返回其组件
        let node = this.tryGetNodeFromPool(key);
        if (node) {
            return node.getComponent(node.name);
        }

        // 如果节点池为空，创建一个新的节点并返回其组件
        node = this.createNewNode(key);
        return node.getComponent(node.name);
    }

    // 获取指定键对应的节点池，如果不存在则创建一个新的节点池的函数
    private createNodePoolIfNotExists(key: string): void {
        if (this.pools[key] == null) {
            this.pools[key] = new cc.NodePool();
        }
    }

    // 尝试从节点池中获取节点，如果能获取到则返回其组件的函数
    private tryGetNodeFromPool(key: string): cc.Node | null {
        if (this.pools[key].size() > 0) {
            let node = this.pools[key].get();
            return node;
        }
        return null;
    }

    // 如果节点池为空，创建一个新的节点并返回其组件的函数
    private createNewNode(key: string): cc.Node {
        let node = cc.instantiate(this.resKey[key]);
        return node;
    }

    recover(key: string, node: cc.Node) {
        // 获取指定键对应的节点池，如果不存在则创建一个新的节点池
        this.createNodePoolIfNotExists(key);

        // 将节点放入对应的节点池中
        this.putNodeIntoPool(key, node);
    }

    // 获取指定键对应的节点池，如果不存在则创建一个新的节点池的函数（与前面重复定义，可考虑提取为公共函数）
    private createNodePoolIfNotExistsForRecover(key: string): void {
        if (this.pools[key] == null) {
            this.pools[key] = new cc.NodePool();
        }
    }

    // 将节点放入对应的节点池中
    private putNodeIntoPool(key: string, node: cc.Node): void {
        this.pools[key].put(node);
    }

}