import { _decorator, assetManager, resources, sp, SpriteFrame, AudioClip, Font } from 'cc';

const { ccclass } = _decorator;

export type ResourceType = typeof SpriteFrame | typeof AudioClip | typeof sp.SkeletonData | typeof Font;

interface ResourceGroup {
    path: string;
    type: ResourceType;
    weight: number;
}

@ccclass('ResourceLoader')
export class ResourceLoader {
    private static _instance: ResourceLoader;

    // 获取单例实例
    public static get instance(): ResourceLoader {
        if (!this._instance) {
            this._instance = new ResourceLoader();
        }
        return this._instance;
    }

    private groups: ResourceGroup[] = [];
    private loadedResources: Map<string, any> = new Map();

    private constructor() {}

    /** 添加资源分组 */
    addGroup(path: string, type: ResourceType, weight: number) {
        this.groups.push({ path, type, weight });
    }

    /** 获取加载好的资源 */
    getResource<T>(name: string): T | undefined {
        return this.loadedResources.get(name) as T;
    }

    /** 释放所有资源（可选） */
    releaseAll() {
        this.loadedResources.forEach((res) => {
            assetManager.releaseAsset(res);
        });
        this.loadedResources.clear();
    }

    /** 加载所有资源（带进度回调） */
    async loadAll(onProgress?: (percent: number) => void, onComplete?: () => void) {
        const totalWeight = this.groups.reduce((sum, g) => sum + g.weight, 0);
        let accumulatedPercent = 0;

        for (const group of this.groups) {
            const groupWeight = group.weight;

            await new Promise<void>((resolve, reject) => {
                resources.loadDir(
                    group.path,
                    group.type,
                    (finished, total) => {
                        const progress = finished / total;
                        const overallPercent = accumulatedPercent + progress * (groupWeight / totalWeight) * 100;
                        onProgress?.(overallPercent);
                    },
                    (err, assets) => {
                        if (err) {
                            console.error(`加载失败: ${group.path}`, err);
                            reject(err);
                            return;
                        }

                        if (assets) {
                            for (const asset of assets) {
                                const name = asset.name;
                                this.loadedResources.set(name, asset);
                            }
                        }

                        accumulatedPercent += (groupWeight / totalWeight) * 100;
                        resolve();
                    }
                );
            });
        }

        onProgress?.(100);
        onComplete?.();
    }
}
