export class ImageToVideo {
    private cStream: MediaStream;
    private recorder: MediaRecorder;
    private chunks: Array<Blob>;
    private wrap: HTMLDivElement;
    private canvas: HTMLCanvasElement;
    private ctx: CanvasRenderingContext2D;
    private images: Array<string>;
    private frame: number;
    private resolve: Function;
    private FPS: number;
    private _codecs: string;
    constructor(images: Array<string>) {
        this._codecs = 'h264';
        this.images = images;
        this.chunks = [];
        this.FPS = this.images.length / 15;
        this.wrap = document.createElement("div");
        this.wrap.style.cssText = `
        position: absolute;
        top: 0;
        left: 0;
        overflow: hidden;
        opacity: 0.01;
        z-index: -9999999;
        max-width: 100%;
        `;
        this.canvas = document.createElement("canvas");
        this.wrap.appendChild(this.canvas);
    }

    get codecs() {
        return this._codecs;
    }

    set codecs(value: string) {
        this._codecs = value;
    }

    getVideo() {
        return new Promise((resolve: any, reject: any) => {
            this.resolve = resolve;
            document.body.appendChild(this.wrap);
            this.frame = 0;
            this.ctx = this.canvas.getContext("2d", { alpha: true });
            const img = new Image();
            img.onload = () => {
                this.canvas.width = img.naturalWidth;
                this.canvas.height = img.naturalHeight;
                this.start();
                this.anim();
            };
            img.src = this.images[0];
        });
    }

    setTimeout(ms: number) {
        return new Promise((resolve: any, reject: any) => {
            setTimeout(() => {
                resolve();
            }, ms);
        });
    }

    anim() {
        const img = new Image();
        img.onload = async () => {
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            this.ctx.drawImage(img, 0, 0);
            if (++this.frame < this.images.length) {
                await this.setTimeout(1000 / this.FPS);
                requestAnimationFrame(this.anim.bind(this));
            } else this.stopRecording();
        };
        img.src = this.images[this.frame];
    }

    start() {
        // set the framerate to 30FPS
        this.cStream = this.canvas.captureStream(30);
        // this.cStream = this.canvas.captureStream(this.images.length / 30);
        // create a recorder fed with our canvas' stream
        const options = {
            // mimeType: 'video/webm',
            // mimeType: "video/webm;codecs=h264",
            mimeType: `video/webm;codecs=${this.codecs}`,
            // mimeType: 'video/webm;codecs="vp9, av1"',
        } as MediaRecorderOptions;
        this.recorder = new MediaRecorder(this.cStream, options);
        // start it
        this.recorder.start();
        // save the chunks
        this.recorder.ondataavailable = this.saveChunks.bind(this);

        this.recorder.onstop = this.exportStream.bind(this);
    }

    saveChunks(e: BlobEvent) {
        this.chunks.push(e.data);
    }

    stopRecording() {
        this.recorder.stop();
    }

    exportStream(e: Event) {
        // combine all our chunks in one blob
        // var blob = new Blob(this.chunks, { type: this.recorder.mimeType });
        var blob = new Blob(this.chunks, { type: 'video/webm' });
        this.resolve(blob);
        this.wrap.remove();
    }
}
