import "./css/media.scss";
import { createElement } from "../functions";
import { createIcon } from "./icon";
import { get } from "../utility";

export function createPicture(url) {
    return createElement('a', a => {
        a.className = 'ui-media-picture';
        a.target = '_blank';
        a.href = url;
    },
        createElement('img', img => {
            img.src = url;
        })
    );
}

function readBlob(blob) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = e => {
            const data = new Uint8Array(e.target.result);
            resolve(data);
        };
        reader.onerror = reject;
        reader.readAsArrayBuffer(blob);
    });
}

function playAmrArray(array) {
    return new Promise((resolve, reject) => {
        const samples = AMR.decode(array);
        if (samples != null) {
            resolve(samples);
        } else {
            reject();
        }
    });
}

function playPcm(samples, ended) {
    return new Promise(resolve => {
        const ctx = new AudioContext();
        ctx.addEventListener('statechange', () => resolve(ctx));
        const source = ctx.createBufferSource();
        if (typeof ended === 'function') {
            source.addEventListener('ended', () => ended(ctx));
        }
        const buffer = ctx.createBuffer(1, samples.length, 8000);
        if (typeof buffer.copyToChannel === 'function') {
            buffer.copyToChannel(samples, 0, 0);
        } else {
            const channelBuffer = buffer.getChannelData(0);
            channelBuffer.set(samples);
        }
        source.buffer = buffer;
        source.connect(ctx.destination);
        ctx.duration = buffer.duration;
        source.start();
        // resolve(ctx);
    });
}

function getTimeLabel(time) {
    time = Math.round(time);
    return String(Math.floor(time / 60)).padStart(2, '0') + ':' + String(time % 60).padStart(2, '0');
}

export function createAudio(mime, url) {
    if ((mime === 'audio/amr' || mime === '.amr') && typeof AMR !== 'undefined') {
        const timestamp = createElement('span', 'ui-media-timestamp');
        timestamp.textContent = '00:00 / 00:00';
        let context;
        let timer;
        return createElement('div', 'ui-media-audio',
            createElement('button', button => {
                button.className = 'play';
                button.addEventListener('click', () => {
                    if (context != null) {
                        clearInterval(timer);
                        context.close();
                        context = null;
                        timestamp.textContent = '00:00 / 00:00';
                        button.className = 'play';
                        button.replaceChildren(createIcon('fa-solid', 'play'));
                        return;
                    }
                    get(url, { accept: mime })
                        .then(r => r.blob())
                        .then(r => readBlob(r))
                        .then(r => playAmrArray(r))
                        .then(r => playPcm(r, ctx => {
                            context = null;
                            clearInterval(timer);
                            timestamp.textContent = '00:00 / ' + getTimeLabel(ctx.duration);
                            button.className = 'play';
                            button.replaceChildren(createIcon('fa-solid', 'play'));
                        }))
                        .then(ctx => {
                            context = ctx;
                            button.className = 'stop';
                            button.replaceChildren(createIcon('fa-solid', 'stop'));
                            const total = getTimeLabel(ctx.duration);
                            const refresh = () => timestamp.textContent = getTimeLabel(ctx.currentTime) + ' / ' + total;
                            refresh();
                            timer = setInterval(refresh, 500);
                        })
                        .catch(e => {
                            clearInterval(timer);
                            console.error(e);
                        });
                });
            },
                createIcon('fa-solid', 'play')
            ),
            timestamp
        );
    }
    return createElement('audio', audio => {
        audio.src = url;
        audio.controls = true;
    });
}

export function createVideo(url) {
    return createElement('video', video => {
        video.className = 'ui-media-video';
        video.src = url;
        video.controls = true;
    });
}

export function createFile(url, icon = 'file-alt') {
    return createElement('div', `ui-media-file ${icon}`,
        createIcon('fa-solid', icon),
        createElement('a', a => {
            a.target = '_blank';
            a.href = url;
            a.innerText = 'Click here to view the file';
        })
    );
}