enum PlayStatus {
    none,
    playBefore,
    play,
    playFail,
    pause
}

enum TriggerAudioListener {
    fail='fail',
    canplay='canplay',
    ended='ended',
    speed='speed',
    status='status',
    clear='clear'
}

class CustomAudio {

    audio:HTMLAudioElement = undefined;

    src:string = '';

    triggers:Record<string, any>={};

    status:PlayStatus = PlayStatus.none

    // 设置播放路径
    setSrc(src:string){

        if (!CustomAudio.supper) return;

        this.destroy();

        if (src && src !== this.src) {

            this.src = src;

            if (this.audio === undefined) {
                this.audio = document.createElement('audio');
                this.audio.setAttribute('style','display:none');
                this.audio.src = src;

                // 播放结束
                this.audio.addEventListener('ended',  ()=> {
                    this.setStatus(PlayStatus.pause);
                    return this.triggerListener(TriggerAudioListener.canplay,{
                        duration:  this.getDuration(this.audio.duration)
                    });
                }, false);

                // 加载就绪
                this.audio.addEventListener('canplay',  ()=> {
                    return this.triggerListener(TriggerAudioListener.canplay,{
                        duration: this.getDuration(this.audio.duration)
                    });
                }, false);


                // 加载失败
                this.audio.addEventListener('error',  ()=> {
                    return this.triggerListener(TriggerAudioListener.fail,{
                        message:'加载失败'
                    });
                }, false);

                document.body.appendChild(this.audio);

            } else {
                this.audio.src = src;
            }

        }

        return this;

    }

    getDuration(duration:number){

        duration = parseFloat(duration.toFixed(2));

        return Math.floor(duration);

    }

    // 播放
    play(){
        if (!this.audio || this.status === PlayStatus.play || this.status === PlayStatus.playBefore) return;
        this.setStatus(PlayStatus.playBefore);
        this.audio.play().then(()=>{
            this.setStatus(PlayStatus.play);
        }).catch(()=>{
            this.setStatus(PlayStatus.playFail);
            return this.triggerListener(TriggerAudioListener.fail,{
                message:'播放失败'
            });
        });

        return this;
    }

    replay(){
        if (!this.audio || this.status === PlayStatus.play || this.status === PlayStatus.playBefore) return;
        if (this.audio.currentTime > 0) {
            this.audio.currentTime = 0;
        }

        return this.play();
    }

    private triggerTime;
    triggerSpeed(){
        clearTimeout(this.triggerTime);

        let params = {
            duration: this.getDuration(this.audio.duration),
            currDuration: this.getDuration(this.audio.currentTime)
        };

        let diff = this.audio.duration - this.audio.currentTime;

        this.triggerListener(TriggerAudioListener.speed,params);


        if (diff > 0) {
            this.triggerTime = setTimeout(()=> this.triggerSpeed(),1000);
        } else {
            return ;
        }


    }

    // 暂停
    paused(){
        if (!this.audio || this.status === PlayStatus.pause) return;
        this.setStatus(PlayStatus.pause);
        this.audio.pause();
        return this;
    }

    setStatus(status:PlayStatus){
        if (this.status !== status) {
            this.status = status;

            if (status === PlayStatus.play) {
                this.triggerSpeed();
            } else {
                clearTimeout(this.triggerTime);
            }

            return this.triggerListener(TriggerAudioListener.status,status);
        }
    }


    addListener(key:TriggerAudioListener,callback:Function) {

        if (!callback) return;

        if (this.triggers[key] === undefined) this.triggers[key] = [callback];
        else this.triggers[key].push(callback);

        return this;

    }

    removeListener(key:TriggerAudioListener,callback:Function) {

        if (!callback || this.triggers[key] === undefined) return;

        let index = this.triggers[key].indexOf(callback);

        if (index>=0) this.triggers[key].splice(index,1);

        return this;

    }

    triggerListener(key:TriggerAudioListener,data?:any) {

        if (this.triggers[key]) {
            this.triggers[key].map((item)=> item && item(data));
        }

    }

    static supper:boolean = !!(document.createElement('audio').canPlayType);


    destroy(){
        clearTimeout(this.triggerTime);

        this.triggerListener(TriggerAudioListener.clear);

        // 清空所有监听事件
        this.triggers = {};

        this.paused();

        this.setStatus(PlayStatus.none);
    }


}

export {CustomAudio,TriggerAudioListener,PlayStatus};

export default new CustomAudio();