let mediaRecorder;
let audioChunks = [];

let audioContext;
let dataArray;
let animationId;
let audioOutSource;

console.log("Asking for Audio permissions...");
window.addEventListener("load", async (event) => {
    await navigator.mediaDevices.getUserMedia({ audio: true });
});

function startButtonPulse(analyser) {
    const button = document.querySelector('#recordbutton');

    function updateScale(analyser) {
        if (!analyser) return;

        analyser.getByteTimeDomainData(dataArray);

        let sum = 0;
        for (let i = 0; i < dataArray.length; i++) {
            const value = dataArray[i] - 128;
            sum += value * value;
        }
        const volume = Math.sqrt(sum / dataArray.length);

        const scale = 1 + Math.min(volume / 25, 0.4); // Scales from 1.0 to 1.2

        button.style.transform = `scale(${scale})`;

        animationId = requestAnimationFrame(function() {
            updateScale(analyser);
        });
    }

    updateScale(analyser);
}

function stopButtonPulse() {
    cancelAnimationFrame(animationId);
    const button = document.querySelector('#recordbutton');
    button.style.transform = 'scale(1)';
}

const startPlayback = async () => {
    const audio_out = document.querySelector('#audioout');
    try {
        console.log("Started playback!");

        // Audio analysis
        if (!audioOutSource) {
            audioContext = new AudioContext();
            audioOutSource = audioContext.createMediaElementSource(audio_out);
            analyser = audioContext.createAnalyser();
            analyser.fftSize = 2048;
            dataArray = new Uint8Array(analyser.frequencyBinCount);
            audioOutSource.connect(analyser);
            analyser.connect(audioContext.destination);
        }

        startButtonPulse(analyser);

        await audio_out.play();

    } catch (err) {
        console.error('Something happend oh no!', err);
        alert('Some error happened during playback! :(');
    }
}

const stopPlayback = async () => {
    const audio_out = document.querySelector('#audioout');
    if (audio_out) {
        stopButtonPulse();
    }
}

const startRecording = async () => {
    try {
        navigator.permissions.query({ name: "microphone" }).then(async (result) => {
            if (result.state === "granted") {
                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                mediaRecorder = new MediaRecorder(stream);
                audioChunks = [];
                console.log("Started recording!");

                // Audio analysis
                audioContext = new AudioContext();
                analyser = audioContext.createAnalyser();
                const source = audioContext.createMediaStreamSource(stream);
                analyser.fftSize = 2048;
                dataArray = new Uint8Array(analyser.frequencyBinCount);
                source.connect(analyser);

                startButtonPulse(analyser);

                mediaRecorder.ondataavailable = async event => {
                    if (event.data.size > 0) {
                        console.log("audio available!");
                        audioChunks.push(event.data);
                        url = "/api/v1/upload";
                        if (mediaRecorder.state === 'inactive') {
                            url = "/api/v1/send";
                        }
                        fetch(url, {
                            method: 'POST',
                            body: event.data,
                        });
                    }
                };

                mediaRecorder.onstop = async () => {
                    console.log("Stopped recording!");
                    stopButtonPulse();
                };

                mediaRecorder.start(1000);
            }
        });
    } catch (err) {
        console.error('Microphone access denied or error:', err);
        alert('Please allow microphone access to record audio.');
    }
};

const stopRecording = () => {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
        mediaRecorder.stop();
    }
};