import { director, Node, instantiate, Prefab, Vec3, v3, SpriteFrame, Sprite, AssetManager, resources, assetManager, AudioClip, Material, Texture2D, Label } from "cc";
import { ResModel } from "../model/ResModel";
import { weiSan } from "./weiSanTools";
import { EventManager, EventData } from "../manager/EventManager";
import { PoolManager } from "../manager/PoolManager";

/** 加载资源相关工具类 */
export class LoadTools {
    /** 单例模式 */
    private static _instance: LoadTools = new LoadTools();
    private constructor() { }
    public static get _ins() {
        return this._instance;
    }

    /**
     * 加载游戏场景 
     * @param sceneName 加载场景的名字
     * @param callFunc 加载回调
     */
    loadScene(sceneName: string, callFunc: any, isClear = true) {
        if (isClear) {
            ResModel._ins.clearResDic();
        }
        director.preloadScene(sceneName, () => {
            director.loadScene(sceneName, callFunc);
        });
    };
    /**
     *  加载resource 下的预制体 资源
     * @param url resource 下的资源路径
     * @param callBack 加载完成回调
     */
    loadResPrefab(url: string, callBack?: any, parent?: Node, Pos?: Vec3) {
        this.loadResAny(url, Prefab, (prefab: Prefab) => {
            let clone = instantiate(prefab);
            if (parent) { parent.addChild(clone) };
            if (Pos) { clone.position = v3(Pos.x, Pos.y, 0) };
            if (callBack != null) {
                callBack(clone);
            }
        })
    }
    /**
     * 加载resource 下的图片资源并渲染到节点上
     * @param url resource 下的资源路径
     * @param callBack 加载完成回调
     */
    loadResSpriteFrame(url: string, sprite: Node, parent?: Node, Pos?: Vec3, callBack?: any) {
        resources.load(url + "/spriteFrame", SpriteFrame, function (error: any, SpriteFrame: SpriteFrame) {
            if (error) {
                weiSan.error(error);
            } else {
                sprite.getComponent(Sprite).spriteFrame = SpriteFrame;
                if (parent) { parent.addChild(sprite) };
                if (Pos) { sprite.position = v3(Pos.x, Pos.y, 0) };
                if (callBack != null) {
                    callBack(sprite);
                }
            }
        });
    };
    /**
     * 加载resource 下的游戏资源
     * @param url resource 下的资源路径
     * @param resType 加载资源的类型
     * @param callBack 加载完成回调
     */
    loadResAny(url: string, resType: any, callBack?: any) {
        resources.load(url, resType, function (error: any, res: any) {
            if (error) {
                weiSan.error(error);
            } else {
                if (callBack != null) {
                    callBack(res);
                }
                if (resType == Prefab) {
                    ResModel._ins.PrefabDic.set(url, res);
                } else if (resType == SpriteFrame) {
                    if (!ResModel._ins.SpriteFrameDic.has(url)) {
                        ResModel._ins.SpriteFrameDic.set(url, res);
                    }
                } else if (resType == AudioClip) {
                    if (!ResModel._ins.AudioClipDic.has(url)) {
                        ResModel._ins.AudioClipDic.set(url, res);
                    }
                } else if (resType == Material) {
                    if (!ResModel._ins.MaterialDic.has(url)) {
                        ResModel._ins.MaterialDic.set(url, res);
                    }
                } else if (resType == Texture2D) {
                    if (!ResModel._ins.TextureDic.has(url)) {
                        ResModel._ins.TextureDic.set(url, res);
                    }
                } else if (resType === Prefab) {
                    if (!ResModel._ins.PrefabDic.has(url)) {
                        ResModel._ins.PrefabDic.set(url, res);
                    }
                }
            }
        });
    }
    /** 加载bundle 场景 */
    loadBundleScene(bundleName: string, sceneName: string, onFinishBack?: () => void, isInScene: boolean = true) {
        assetManager.loadBundle(
            bundleName,
            (err: any, bundle: AssetManager.Bundle) => {
                if (err) {
                    console.log(err);
                }
                else {
                    if (!isInScene) { return; }
                    bundle.loadScene(sceneName, (err, scene) => {
                        if (onFinishBack) {
                            onFinishBack();
                        }
                        director.runScene(scene);
                    });
                }
            }
        );
    }


    /**
     * 分帧加载预制体节点
     * @param prefabName 要加载的预制体名称
     * @param perFrameNum 每帧加载的数量
     * @param totalNum 总共需要加载的数量
     * @param usePool 是否使用对象池，默认为true
     * @param callBack 对每个创建的节点进行操作的回调函数
     * @returns Promise<Node[]> 返回所有创建的节点数组
     */
    loadPrefabByFrame(prefabName: string, perFrameNum: number, totalNum: number, usePool: boolean = true, callBack?: (node: Node, index: number) => void): Promise<Node[]> {
        return new Promise((resolve, reject) => {
            // 参数验证
            if (!prefabName || prefabName.trim() === '') {
                const error = 'prefabName cannot be empty';
                weiSan.error(error);
                reject(new Error(error));
                return;
            }

            if (perFrameNum <= 0) {
                const error = 'perFrameNum must be greater than 0';
                weiSan.error(error);
                reject(new Error(error));
                return;
            }

            if (totalNum <= 0) {
                const error = 'totalNum must be greater than 0';
                weiSan.error(error);
                reject(new Error(error));
                return;
            }

            // 触发加载开始事件
            EventManager.dispatchEvent(EventData.PREFAB_LOAD_START, {
                prefabName: prefabName,
                totalNum: totalNum,
                usePool: usePool
            });

            // 创建节点的函数
            const createNodeFunction = (prefab?: Prefab): Node | null => {
                if (usePool) {
                    // 使用对象池创建节点
                    return PoolManager._ins.getNode(prefabName);
                } else {
                    // 使用传统方式创建节点
                    if (!prefab) {
                        weiSan.error(`Prefab is required when not using pool: ${prefabName}`);
                        return null;
                    }
                    return instantiate(prefab);
                }
            };

            if (usePool) {
                // 使用对象池时，直接开始分帧创建
                this.startFrameBasedCreation(prefabName, perFrameNum, totalNum, usePool, callBack, createNodeFunction, resolve, reject);
            } else {
                // 不使用对象池时，先加载预制体资源
                this.loadResAny(prefabName, Prefab, (prefab: Prefab) => {
                    if (!prefab) {
                        const error = `Failed to load prefab: ${prefabName}`;
                        weiSan.error(error);
                        reject(new Error(error));
                        return;
                    }
                    this.startFrameBasedCreation(prefabName, perFrameNum, totalNum, usePool, callBack, createNodeFunction, resolve, reject, prefab);
                });
            }
        });
    }

    /**
     * 开始分帧创建节点的核心逻辑
     */
    private startFrameBasedCreation(
        prefabName: string,
        perFrameNum: number,
        totalNum: number,
        usePool: boolean,
        callBack: ((node: Node, index: number) => void) | undefined,
        createNodeFunction: (prefab?: Prefab) => Node | null,
        resolve: (value: Node[]) => void,
        reject: (reason?: any) => void,
        prefab?: Prefab
    ) {
        // 开始分帧创建节点
        const createdNodes: Node[] = [];
        let currentCount = 0;

        const createNodesPerFrame = () => {
            const remainingCount = totalNum - currentCount;
            const currentFrameCount = Math.min(perFrameNum, remainingCount);

            // 创建当前帧的节点
            for (let i = 0; i < currentFrameCount; i++) {
                try {
                    const node = createNodeFunction(prefab);
                    if (!node) {
                        const error = `Failed to create node: ${prefabName}`;
                        weiSan.error(error);
                        reject(new Error(error));
                        return;
                    }

                    createdNodes.push(node);

                    // 执行回调函数
                    if (callBack) {
                        try {
                            callBack(node, currentCount);
                        } catch (callbackError) {
                            weiSan.warn(`Callback error for node ${currentCount}: ${callbackError}`);
                        }
                    }

                    currentCount++;
                } catch (error) {
                    weiSan.error(`Error creating node instance: ${error}`);
                    reject(new Error(`Error creating node instance: ${error}`));
                    return;
                }
            }

            // 计算进度并触发进度事件
            const progress = (currentCount / totalNum) * 100;
            EventManager.dispatchEvent(EventData.PREFAB_LOAD_PROGRESS, {
                prefabName: prefabName,
                currentNum: currentCount,
                totalNum: totalNum,
                progress: progress
            });

            // 检查是否完成
            if (currentCount >= totalNum) {
                // 触发完成事件
                EventManager.dispatchEvent(EventData.PREFAB_LOAD_COMPLETE, {
                    prefabName: prefabName,
                    totalNum: totalNum,
                    nodes: createdNodes
                });

                weiSan.log(`Successfully loaded ${totalNum} instances of prefab: ${prefabName}`);
                resolve(createdNodes);
            } else {
                // 继续下一帧，使用 setTimeout 来实现分帧
                setTimeout(() => {
                    createNodesPerFrame();
                }, 0);
            }
        };

        // 开始第一帧的创建
        createNodesPerFrame();
    }
}