/**
 * 音频控制模块
*/

import { Store } from "./Store";


export class Audio {
    /**
     * 当前正在播放的背景音乐剪辑
     */
    public static bgmClip: string = null;
    /**
     * 背景音乐音频id
     */
    public static bgmAudioId: number = null;
    /**
     * 是否启用背景音乐
     */
    public static isEnaledMusic: boolean = true;
    /**
     * 是否启用音效
     */
    public static isEnaledSound: boolean = true;
    /**
     * 音效ID
     */
    private static soundIds: Array<number> = [];

    /** 所有已加载的音频剪辑 */
    public static audioClips: cc.AudioClip[] = [];

    /**
     * 初始化AudioEngine
     */
    static initAudioEngine(): void {
        try {
            Audio.enableMusic(Store.getBool('enabledMusic', true));
            Audio.enableSound(Store.getBool('enabledEffect', true));
        } catch (e) {
            Audio.enableMusic(true);
            Audio.enableSound(true);
        }
    }

    /**
     * 播放背景音乐
     * @param audioClip 音频剪辑
     * @param volume 音频音量
     */
    static playMusic(audioClip: any, volume: number = 1): number {
        if (audioClip === null || audioClip === undefined) {
            return;
        }

        if (audioClip === Audio.bgmClip) {
            if (Audio.isEnaledMusic) {
                cc.audioEngine.resume(Audio.bgmAudioId);
            } else {
                cc.audioEngine.pause(Audio.bgmAudioId);
            }
            return Audio.bgmAudioId;
        }
        if (Audio.bgmAudioId !== null && Audio.bgmAudioId !== undefined) {
            cc.audioEngine.stop(Audio.bgmAudioId);
        }

        Audio.bgmClip = audioClip;
        Audio.bgmAudioId = cc.audioEngine.play(audioClip, true, volume);

        if (Audio.isEnaledMusic) {
            cc.audioEngine.resume(Audio.bgmAudioId);
        } else {
            cc.audioEngine.pause(Audio.bgmAudioId);
        }

        return Audio.bgmAudioId;
    };

    /**
     * 播放音效
     * @param audioClip 音频剪辑
     * @param isLoop 是否循环播放
     * @param volume 音量
     */
    static playSound(audioClip: any, isLoop?: boolean, volume: number = 1): number {
        if (audioClip === null || audioClip === undefined || !Audio.isEnaledSound) {
            return;
        }
        let id = cc.audioEngine.play(audioClip, isLoop || false, volume);
        Audio.soundIds.push(id);
        return id;
    };

    /**
     * 动态加载音频剪辑并播放
     * @param audioClipPath 音频剪辑在resources下的路径
     * @param isLoop 是否循环播放
     * @param volume 播放音量，取值区间[0.0, 1.0]，默认为1.0
     */
    static async playEffect(audioClipPath: string, isLoop?: boolean, volume: number = 1) {
        try {
            const audio = Audio.audioClips[audioClipPath] || await Audio.loadAudioClip(audioClipPath);
            return Audio.playSound(audio, isLoop, volume);
        } catch (error) {
        }
    }

    /**
     * 通过resources路径播放循环背景音效
     * @param audioPath 音频路径
     * @param volume 音量
     */
    static async playMusicByPath(audioPath: string, volume: number = 1) {
        const audio = await Audio.loadAudioClip(audioPath);
        Audio.playMusic(audio, volume);
    }

    /**
     * 通过resources路径播放音效
     * @param audioPath 音频路径
     * @param isLoop 是否循环
     * @param volume 音量
     */
    static async playSoundByPath(audioPath: string, isLoop?: boolean, volume: number = 1) {
        if (Audio.audioClips[audioPath]) {
            return Audio.playSound(Audio.audioClips[audioPath], isLoop, volume);
        }
        const audio = await Audio.loadAudioClip(audioPath);
        return Audio.playSound(audio, isLoop, volume);
    }

    /**
     * 动态加载音频资源
     * @param url 音频资源地址
     */
    static loadAudioClip(url: string) {
        return new Promise((resolve, reject) => {
            if (Audio.audioClips[url]) { return resolve(Audio.audioClips[url]); }
            let data = url.split(':')
            this.getBundle(data[0], (err, bundle: cc.AssetManager.Bundle) => {
                bundle && bundle.load(data[1], cc.AudioClip, (err, clip: cc.AudioClip) => {
                    if (err) { return reject(err); }
                    Audio.audioClips[url] = clip;
                    return resolve(clip);
                });
            });
        });
    }

    static preloadSound(url: string) {
        if (Audio.audioClips[url]) { return; }
        let data = url.split(':');
        cc.assetManager.loadBundle(data[0], (err, bundle: cc.AssetManager.Bundle) => {
            bundle.load(data[1], cc.AudioClip, (err, clip: cc.AudioClip) => {
                if (err) { return; }
                Audio.audioClips[url] = clip;
            });
        })
    }

    private static async getBundle(name: string, complete: Function) {
        const bundle = cc.assetManager.getBundle(name);
        if (bundle) {
            complete && complete(null, bundle);
            return;
        }
        cc.assetManager.loadBundle(name, (err, bundle) => {
            if (err) {
                complete && complete(err, bundle);
                return;
            }
            complete && complete(err, bundle);
        });
    }

    /**
     * 启用/禁用背景音乐
     * @param isEnabled 是否开启背景音乐
     */
    static enableMusic(isEnabled: boolean): void {
        Audio.isEnaledMusic = isEnabled;
        Store.setBool('enabledMusic', isEnabled);

        try {
            if (Audio.bgmAudioId !== 0 && !Audio.bgmAudioId) { return; }

            if (Audio.isEnaledMusic) {
                cc.audioEngine.resume(Audio.bgmAudioId);
            } else {
                cc.audioEngine.pause(Audio.bgmAudioId);
            }
        } catch (e) {
            // throw e;
        }
    }

    /**
     * 启用/禁用音效
     * @param isEnabled 是否启用音效
     */
    static enableSound(isEnabled: boolean): void {
        Audio.isEnaledSound = isEnabled;
        Store.setBool('enabledEffect', isEnabled);

        for (let i = 0; i < Audio.soundIds.length; ++i) {
            cc.audioEngine.stop(Audio.soundIds[i]);
        }
        Audio.soundIds = [];
    }

    /**
     * 停止所有音效
     */
    static stopAllSounds(isStopMusic: boolean = false): void {
        if (isStopMusic) {
            cc.audioEngine.stopAll();
        } else {
            for (let i = 0; i < Audio.soundIds.length; ++i) {
                cc.audioEngine.stop(Audio.soundIds[i]);
            }
        }
    }

    /**
     * 停止音效播放
     */
    static stopSound(audioId): void {
        cc.audioEngine.stop(audioId);
    }

}

// 游戏初始化完成
if (cc.game && cc.game.on) {
    cc.game.on((cc.game as any).EVENT_ENGINE_INITED, (data: any) => {
        Audio.initAudioEngine();
    });
}