import { AudioClip, Node, AudioSource, tween } from "cc";
import { ResModel } from "../model/ResModel";
import { LoadTools } from "./LoadTools";

/** 声音相关工具类 */
export class AudioTools {
    /** 单例模式 */
    private static _instance: AudioTools = new AudioTools();
    private constructor() { }
    public static get _ins() {
        return this._instance;
    }
    private audioDic: Map<string, AudioSource> = new Map();
    private audioVolumeDic: Map<string, number> = new Map();
    private audioPermanentDic: Map<AudioSource, boolean> = new Map();
    bgAudio: AudioSource;  //背景音乐
    isPlayAudio: boolean = true; //是否播放音效
    isPlayBG: boolean = true; //是否播放音乐

    /** 播放背景音乐 */
    playBG(audioUrl: string, value = 0.5) {
        if (!this.isPlayBG) { return; }
        if (ResModel._ins.AudioClipDic.get(audioUrl) != null) {
            this.bgAudio = this.newAudioSource(ResModel._ins.AudioClipDic.get(audioUrl), value, true);
            this.audioDic.set(audioUrl, this.bgAudio);
            this.audioVolumeDic.set(audioUrl, value);
            this.audioPermanentDic.set(this.bgAudio, true);
            return this.bgAudio;
        } else {
            LoadTools._ins.loadResAny('music/' + audioUrl + '.mp3', AudioClip, (audio: AudioClip) => {
                this.bgAudio = this.newAudioSource(audio, value, true);
                this.audioDic.set(audioUrl, this.bgAudio);
                this.audioVolumeDic.set(audioUrl, value);
                this.audioPermanentDic.set(this.bgAudio, true);
                return this.bgAudio;
            });
        }
    };
    /**
     * 播放游戏音效
     * @param audioUrl 音效文件的res/music/的路径 或者 resArr拖动的名字
     * @param value 音量大小
     * @param isLoop 是否循环播放
     * @param isPermanent 是否永久播放
     */
    playAudio(audioUrl: string, value = 0.5, isLoop = false, isPermanent = false) {
        if (!this.isPlayAudio) { return; }
        if (ResModel._ins.AudioClipDic.get(audioUrl) != null) {
            let audioE = this.newAudioSource(ResModel._ins.AudioClipDic.get(audioUrl), value, isLoop);
            this.audioDic.set(audioUrl, audioE);
            this.audioVolumeDic.set(audioUrl, value);
            this.audioPermanentDic.set(audioE, isPermanent);
            return audioE;
        } else {
            LoadTools._ins.loadResAny('music/' + audioUrl + '.mp3', AudioClip, (audio: AudioClip) => {
                let audioE = this.newAudioSource(audio, value, isLoop);
                this.audioDic.set(audioUrl, audioE);
                this.audioVolumeDic.set(audioUrl, value);
                this.audioPermanentDic.set(audioE, isPermanent);
                return audioE;
            });
        }
    };
    /** 停止播放某个音效 */
    stopAudio(audioName: string) {
        let audioE = this.audioDic.get(audioName);
        if (audioE != null) {
            audioE.stop();
        }
    }
    /**
     * 新建一个audioSource 来播放音效
     * @param audioUrl 音效文件的res/music/的路径 或者 resArr拖动的名字
     * @param value 音量大小
     * @param isLoop 是否循环播放
     */
    playAudioSource(audioUrl: string, value = 0.5, isLoop = false) {
        if (!this.isPlayAudio) { return; }
        if (ResModel._ins.AudioClipDic.get(audioUrl) != null) {
            return this.newAudioSource(ResModel._ins.AudioClipDic.get(audioUrl), value, isLoop);
        } else {
            LoadTools._ins.loadResAny(audioUrl, AudioClip, (audioE: AudioClip) => {
                this.newAudioSource(audioE, value, isLoop);
            });
        }
    }
    /** 新建一个 audioSource 播放音效 */
    newAudioSource(audioClip: AudioClip, value = 0.5, isLoop = false) {
        if (!this.isPlayAudio) { return; }
        let node = new Node();
        let audioE = node.addComponent(AudioSource);
        audioE.clip = audioClip;
        audioE.loop = isLoop;
        audioE.volume = value;

        audioE.play();
        if (isLoop == false) {
            tween(node).delay(audioE.duration + 0.1)
                .removeSelf().union().start();
        }
        return audioE;
    };

    /** 停止所有音效 */
    stopAllAudio() {
        this.isPlayAudio = false;
        this.isPlayBG = false;
        for (let audioE of this.audioDic.values()) {
            audioE.stop();
        }
    }

    /** 恢复所有音效 */
    resumeAllAudio() {
        for (let audioE of this.audioDic.values()) {
            if (this.audioPermanentDic.get(audioE) && !audioE.playing) {
                audioE.play();
            }
            audioE.volume = this.audioVolumeDic.get(audioE.clip.name);
        }
        this.isPlayAudio = true;
        this.isPlayBG = true;
    }

    /**
     * 恢复指定音效
     * @param audioName 音效文件的res/music/的路径 或者 resArr拖动的名字
     */
    resumeAudioByName(audioName: string) {
        let audioE = this.audioDic.get(audioName);
        if (audioE != null) {
            if (!audioE.playing) {
                audioE.play();
            }
            audioE.volume = this.audioVolumeDic.get(audioE.clip.name);
        }
    }

    /**
     * 设置指定音效的音量
     * @param audioName 音效文件的res/music/的路径 或者 resArr拖动的名字
     * @param value 音量大小
     */
    setAudioVolume(audioName: string, value: number) {
        let audioE = this.audioDic.get(audioName);
        if (audioE != null) {
            audioE.volume = value;
            this.audioVolumeDic.set(audioName, value);
        }
    }

    /**
     * 设置指定音效的循环播放
     * @param audioName 音效文件的res/music/的路径 或者 resArr拖动的名字
     * @param isLoop 是否循环播放
     */
    setAudioLoop(audioName: string, isLoop: boolean) {
        let audioE = this.audioDic.get(audioName);
        if (audioE != null) {
            audioE.loop = isLoop;
        }
    }

    /**
     * 设置指定音效的静音
     * @param audioName 音效文件的res/music/的路径 或者 resArr拖动的名字
     */
    muteAudio(audioName: string) {
        let audioE = this.audioDic.get(audioName);
        if (audioE != null) {
            audioE.volume = 0.0;
        }
    }

    /**
     * 设置所有音效的静音
     */
    muteAllAudio() {
        for (let audioE of this.audioDic.values()) {
            audioE.volume = 0.0;
        }
        this.isPlayAudio = false;
        this.isPlayBG = false;
    }
}
