import { EventDispatcher, Event } from "../../2d/events";
import { Sound, $pushSoundChannel } from "../Sound";
import { SoundChannel } from "../SoundChannel";
import { WebAudioSoundChannel } from "./WebAudioSoundChannel";





export class WebAudioDecode {
    /**
     * @private
     */
    public static ctx;

    /**
     * @private
     */
    public static decodeArr: any[] = [];
    /**
     * @private
     */
    private static isDecoding: boolean = false;

    /**
     * @private
     *
     */
    static decodeAudios() {
        if (WebAudioDecode.decodeArr.length <= 0) {
            return;
        }
        if (WebAudioDecode.isDecoding) {
            return;
        }
        WebAudioDecode.isDecoding = true;
        let decodeInfo = WebAudioDecode.decodeArr.shift();

        WebAudioDecode.ctx.decodeAudioData(decodeInfo["buffer"], function (audioBuffer) {
            decodeInfo["self"].audioBuffer = audioBuffer;

            if (decodeInfo["success"]) {
                decodeInfo["success"]();
            }
            WebAudioDecode.isDecoding = false;
            WebAudioDecode.decodeAudios();
        }, function () {
            console.error("解析错误")

            if (decodeInfo["fail"]) {
                decodeInfo["fail"]();
            }
            WebAudioDecode.isDecoding = false;
            WebAudioDecode.decodeAudios();
        });
    }

}

/**
 * @private
 * @inheritDoc
 */
export class WebAudioSound extends EventDispatcher implements Sound {
   
    /**
     * @private
     */
    private url: string;
    /**
     * @private
     */
    private loaded: boolean = false;

    /**
     * @private
     * @inheritDoc
     */
    constructor() {
        super();
    }


    /**
     * @private
     */
    private audioBuffer: AudioBuffer;


    public get length(): number {
        if (this.audioBuffer) {
            return this.audioBuffer.duration;
        }

        throw new Error("sound not loaded!");

        //return 0;
    }

    public load(url: string): void {
        let self = this;

        this.url = url;

        let request = new XMLHttpRequest();
        request.open("GET", url, true);
        request.responseType = "arraybuffer";
        request.onreadystatechange = function () {
            if (request.readyState == 4) {// 4 = "loaded"
                let ioError = (request.status >= 400 || request.status == 0);
                if (ioError) {//请求错误
                    self.dispatchEvent(Event.ERROR);
                } else {
                    WebAudioDecode.decodeArr.push({
                        "buffer": request.response,
                        "success": onAudioLoaded,
                        "fail": onAudioError,
                        "self": self,
                        "url": self.url
                    });
                    WebAudioDecode.decodeAudios();
                }
            }
        }
        request.send();

        function onAudioLoaded(): void {
            self.loaded = true;
            self.dispatchEvent(Event.COMPLETE);
        }

        function onAudioError(): void {
            self.dispatchEvent(Event.ERROR);
        }
    }

    /**
     * @inheritDoc
     */
    public play(startTime?: number, loops?: number): SoundChannel {
        startTime = +startTime || 0;
        loops = +loops || 0;



        let channel = new WebAudioSoundChannel();
        channel.$url = this.url;
        channel.$loops = loops;
        channel.$audioBuffer = this.audioBuffer;
        channel.$startTime = startTime;
        channel.$play();

        $pushSoundChannel(channel);

        return channel;
    }

    /**
     * @inheritDoc
     */
    public close() {
    }
}
