import { Asset } from 'cc';
import { BundleProxy } from './BundleProxy';

/**
 * 资源代理类
 * 职责:
 * - 封装单个资源的异步加载逻辑
 * - 管理资源的缓存状态
 * - 提供资源的加载、预加载、释放接口
 */
export class ResProxy<T extends Asset> {
    private _bundleProxy: BundleProxy;
    private _path: string;
    private _type: new (...args: any[]) => T;
    private _asset: T | null = null;
    private _loading: Promise<T> | null = null;
    private _preloading: Promise<void> | null = null;

    constructor(
        bundleProxy: BundleProxy,
        path: string,
        type: new (...args: any[]) => T
    ) {
        this._bundleProxy = bundleProxy;
        this._path = path;
        this._type = type;
    }

    /**
     * 获取资源路径
     */
    get path(): string {
        return this._path;
    }

    /**
     * 获取Bundle名称
     */
    get bundleName(): string {
        return this._bundleProxy.bundleName;
    }

    /**
     * 获取资源实例(同步)
     */
    get asset(): T | null {
        return this._asset;
    }

    /**
     * 是否已加载
     */
    get isLoaded(): boolean {
        return this._asset !== null;
    }

    /**
     * 是否正在加载中
     */
    get isLoading(): boolean {
        return this._loading !== null;
    }

    /**
     * 是否正在预加载中
     */
    get isPreloading(): boolean {
        return this._preloading !== null;
    }

    /**
     * 加载资源
     * @returns Promise<资源>
     */
    async load(): Promise<T> {
        // 如果已经加载完成,直接返回
        if (this._asset) {
            console.log(`[ResProxy] 从缓存获取资源: ${this.bundleName}/${this._path}`);
            return this._asset;
        }

        // 如果正在加载中,返回加载Promise
        if (this._loading) {
            return this._loading;
        }

        // 开始加载
        this._loading = this._bundleProxy.loadRes(this._path, this._type);

        try {
            this._asset = await this._loading;
            return this._asset;
        } finally {
            this._loading = null;
        }
    }

    /**
     * 预加载资源
     * @param onProgress 进度回调
     * @returns Promise<void>
     */
    async preload(onProgress?: (finished: number, total: number) => void): Promise<void> {
        // 如果已经加载完成,直接返回
        if (this._asset) {
            console.log(`[ResProxy] 资源已加载,无需预加载: ${this.bundleName}/${this._path}`);
            return;
        }

        // 如果正在预加载中,返回预加载Promise
        if (this._preloading) {
            return this._preloading;
        }

        // 如果正在加载中,等待加载完成
        if (this._loading) {
            await this._loading;
            return;
        }

        // 开始预加载
        this._preloading = this._bundleProxy.preload(this._path, this._type, onProgress);

        try {
            await this._preloading;
        } finally {
            this._preloading = null;
        }
    }

    /**
     * 释放资源
     */
    release(): void {
        if (!this._asset) {
            console.warn(`[ResProxy] 资源未加载,无法释放: ${this.bundleName}/${this._path}`);
            return;
        }

        this._bundleProxy.release(this._path);
        this._asset = null;
        console.log(`[ResProxy] 释放资源: ${this.bundleName}/${this._path}`);
    }

    /**
     * 清除缓存(不释放资源)
     */
    clearCache(): void {
        this._asset = null;
        this._loading = null;
        this._preloading = null;
    }

    /**
     * 重新加载资源
     * @returns Promise<资源>
     */
    async reload(): Promise<T> {
        if (this._asset) {
            this.release();
        }
        return this.load();
    }

    /**
     * 获取完整路径
     */
    getFullPath(): string {
        return `${this.bundleName}/${this._path}`;
    }
}
