import { Node, NodePool, Prefab, instantiate, resources } from "cc";

/**
 * 对象池管理器
 * 用于创建和管理对象池
 */
export default class PoolManager {
    private static pools: { [key: string]: NodePool } = {};
    private static prefabPath: string = 'prefab/element/';
    private static maxPoolSize: number = 100; // 默认最大对象池容量

    /**
     * 获取对象
     * @param prefabName 预制体名称
     * @param savedComponents 需要保存属性的组件数组
     * @returns Promise<Node | null> 获取到的对象，如果对象池中没有可用对象则返回 null
     */
    public static async getObject(prefabName: string, savedComponents?: Function[]): Promise<Node | null> {
        const pool = this.pools[prefabName];

        if (!pool || pool.size() === 0) {
            const obj = await this.createNewObject(prefabName);
            if (obj && savedComponents) {
                this.resetComponents(obj, savedComponents);
            }
            return obj;
        }

        const obj = pool.get();
        if (savedComponents) {
            this.resetComponents(obj, savedComponents);
        }
        return obj;
    }

    /**
     * 将对象放回对象池
     * @param prefabName 预制体名称
     * @param obj 对象
     */
    public static putObject(prefabName: string, obj: Node) {
        let pool = this.pools[prefabName];

        if (!pool) {
            pool = new NodePool();
            this.pools[prefabName] = pool;
        }

        if (pool.size() < this.maxPoolSize) {
            pool.put(obj);
        } else {
            obj.destroy();  // 超出容量限制时销毁对象
        }
    }

    /**
     * 创建新的对象
     * @param prefabName 预制体名称
     * @returns Promise<Node | null> 创建的对象，如果加载预制体失败则返回 null
     */
    private static createNewObject(prefabName: string): Promise<Node | null> {
        return new Promise((resolve, reject) => {
            const prefabPath = `${this.prefabPath}${prefabName}`;
            resources.load(prefabPath, Prefab, (error, prefab) => {
                if (error) {
                    console.warn(`无法加载预制体 "${prefabName}"，请检查预制体路径`);
                    resolve(null);
                    return;
                }

                const obj = instantiate(prefab);
                resolve(obj);
            });
        });
    }

    /**
     * 重置对象的组件属性
     * @param obj 需要重置的对象
     * @param savedComponents 需要重置的组件数组
     */
    private static resetComponents(obj: Node, savedComponents: Function[]) {
        savedComponents.forEach(resetFn => resetFn(obj));
    }

    /**
     * 设置对象池最大容量
     * @param maxSize 最大容量
     */
    public static setMaxPoolSize(maxSize: number) {
        this.maxPoolSize = maxSize;
    }

    /**
     * 设置预制体的资源路径
     * @param path 资源路径
     */
    public static setPrefabPath(path: string) {
        this.prefabPath = path;
    }
}
