<!DOCTYPE html>
<html lang="en">
<!--
    Caleb, KO4UYJ
    Inspired by https://github.com/firealarmss/dvm2web/
-->
<head>
    <title>Listening to <%= hostCallsign %>'s Allstar Node</title>
    <script src="/public/pcm-player.js"></script>
    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
    <style>
        body {
            background-color: #000101;
            text-align: center;
            color: white;
        }

        .container {
            position: relative;
            display: inline-block;
        }

        .image {
            display: block;
        }

        .line2 {
            position: absolute;
            top: 43%;
            left: 51%;
            transform: translate(-50%, -50%);
            z-index: 1;
            color: black;
            font-size: 25px;
            font-family: Helvetica, serif;
            font-weight: bold;
            text-align: center;
        }

        .line1 {
            position: absolute;
            top: 32%;
            left: 51%;
            transform: translate(-50%, -50%);
            z-index: 1;
            color: black;
            font-size: 20px;
            font-family: Helvetica, serif;
            font-weight: bold;
            text-align: center;
        }

        .pwr_button {
            position: absolute;
            border-radius: 100%;
            cursor: pointer;
            top: 69%;
            left: 19%;
            transform: translate(-50%, -50%);
            z-index: 1;
            font-size: 13px;
            font-family: Helvetica,serif;
            font-weight: bold;
            text-align: center;
            color: transparent;
            background: transparent;
            padding: 0;
            margin: 0;
            border: 0;
        }
        .emerg_button {
            position: absolute;
            border-radius: 100%;
            cursor: pointer;
            top: 16%;
            left: 96%;
            transform: translate(-50%, -50%);
            z-index: 1;
            font-size: 13px;
            font-family: Helvetica,serif;
            font-weight: bold;
            text-align: center;
            color: transparent;
            background: transparent;
            padding: 0;
            margin: 0;
            border: 0;
            height: 20px;
        }
    </style>
</head>

<body>
<div style="text-align: center;">
    <div class="container">
        <img class="image" src="/public/o5.jpg" alt="Head">
        <div id="line1" class="line1"></div>
        <div id="line2" class="line2"></div>
        <button id="pwr_button" class="pwr_button" onclick="radioPower()">PW</button>
        <button id="emerg_button" class="emerg_button" onclick="send_emerg()">EM</button>
    </div>
</div>

<script>
    let socket = io();

    let pwr_on = false;
    let voiceActive = false;
    let talking;
    let current_channel = "<%= hostCallsign %>'s Allstar";
    let current_zone = "Centrunk";
    let player;
    let audioCtx;
    let mediaStream;
    let audioStreamNode;

    function start() {
        function resampleAudio(audioBuffer, targetSampleRate) {
            const samples = audioBuffer.length;
            const ratio = audioCtx.sampleRate / targetSampleRate;
            const newSamples = Math.round(samples / ratio);
            const result = new Float32Array(newSamples);
            let offsetResult = 0;
            let offsetBuffer = 0;

            while (offsetResult < result.length) {
                const nextOffsetBuffer = Math.round((offsetResult + 1) * ratio);
                let accum = 0;
                let count = 0;
                for (let i = offsetBuffer; i < nextOffsetBuffer && i < samples; i++) {
                    accum += audioBuffer[i];
                    count++;
                }
                result[offsetResult] = accum / count;
                offsetResult++;
                offsetBuffer = nextOffsetBuffer;
            }

            return result;
        }
        audioCtx = new (window.AudioContext || window.webkitAudioContext)();
        // Initial support for sending audio to allstar from browser
        // TODO: Make work
    /*
       navigator.mediaDevices.getUserMedia({ audio: true })
            .then((stream) => {
                mediaStream = stream;
                audioStreamNode = audioCtx.createMediaStreamSource(stream);

                // Create a ScriptProcessorNode to process audio data in real-time
                const scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
                audioStreamNode.connect(scriptNode);
                scriptNode.connect(audioCtx.destination);

                scriptNode.onaudioprocess = function (e) {
                    const inputData = e.inputBuffer.getChannelData(0);
                    // Resample the audio data to 8000Hz sample rate
                    const resampledData = resampleAudio(inputData, 8000);
                    // Send audio data to the server via WebSocket
                    socket.emit('sendAudio', resampledData);
                };
            })
            .catch((err) => {
                console.error("Error accessing microphone:", err);
            });
    */

        pwr_on = true;
        setTimeout(function () {
      //      document.getElementById('line1').innerHTML = current_zone;
            document.getElementById('line2').innerHTML = current_channel;

            player = new PCMPlayer({
                encoding: '16bitInt',
                channels: 1,
                sampleRate: 8000,
                flushingTime: 2000,
                onAudioEnd: audioStopped,
                onAudioStart: audioStarted
            });
            socket.on('channelAudio', function (msg) {
                const rcv_data = JSON.parse(msg);
                let audioData = new Uint8Array(rcv_data.audio.data);
                player.feed(audioData);
            });
            let lineToggle = false;
            let intervalId;

            socket.on('disconnect', function () {
                intervalId = setInterval(toggleLines, 2000);
            });
            socket.on('connection', function (){
                console.log("reconnected");
                clearInterval(intervalId);
                const currentChannelElement = document.getElementById('line2');
                currentChannelElement.innerHTML = current_channel;
            });

            function toggleLines() {
                const line2Element = document.getElementById('line2');
                const currentChannelElement = document.getElementById('line2');

                if (lineToggle) {
                    line2Element.innerHTML = "Site Trunking";
                    currentChannelElement.innerHTML = current_channel;
                } else {
                    line2Element.innerHTML = current_channel;
                    currentChannelElement.innerHTML = "Site Trunking";
                }

                lineToggle = !lineToggle;
            }

            function audioStopped() {
                //ig you could do som useful here? This was from dvm2web
            }

            function audioStarted() {
                //ig you could do som useful here? This was from dvm2web
            }
        }, 1500);
        //A dvm2web whacker feature that is just too cool to remove
        socket.on("EMERG", function(msg){
            let dstId = msg.dstId;
            let srcId = msg.srcId;
            let lineToggle = false;
            let intervalId;

            if (!voiceActive && dstId === current_channel) {
                emergency_tone_generate();
                intervalId = setInterval(toggleLines, 2000);
                voiceActive = true;
            }
            function toggleLines() {
                const line2Element = document.getElementById('line2');
                const currentChannelElement = document.getElementById('line2');

                if (lineToggle) {
                    line2Element.innerHTML = "EM: " + srcId;
                    currentChannelElement.innerHTML = current_channel;
                } else {
                    line2Element.innerHTML = current_channel;
                    currentChannelElement.innerHTML = "EM: " + srcId;
                }

                lineToggle = !lineToggle;
            }
            setTimeout(function (){
                clearInterval(intervalId);
                document.getElementById("line2").innerHTML = current_channel;
                voiceActive = false;
            }, 20000);
        });
        function emergency_tone_generate(){
            beep(610, 500, 20, 'sine');
            setTimeout(function () {
                beep(910, 500, 20, 'sine');
            }, 500);
            setTimeout(function () {
                beep(610, 500, 20, 'sine');
            }, 1000);
            setTimeout(function () {
                beep(910, 500, 20, 'sine');
            }, 1500);
        }


        function beep(frequency, duration, volume, type) {

            var oscillator = audioCtx.createOscillator();
            var gainNode = audioCtx.createGain();

            oscillator.connect(gainNode);
            gainNode.connect(audioCtx.destination);
            vol = 1;
            gainNode.gain.value = vol;
            oscillator.frequency.value = frequency;
            oscillator.type = type;

            oscillator.start();

            setTimeout(
                function () {
                    oscillator.stop();
                },
                duration
            );
        }
    }
    async function radioOff(){
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
        }
        pwr_on = false;
        await socket.off('channelAudio');
        document.getElementById('line1').innerHTML = "PHP Says goodbye";
        document.getElementById('line2').innerHTML = "https://discord.gg/ctrs";
        setTimeout(function (){
            document.getElementById('line1').innerHTML = "";
            document.getElementById('line2').innerHTML = "";
        }, 1500);
    }
    function radioPower(){
        if (pwr_on){
            radioOff();
        } else {
            start();
        }
    }
    function send_emerg(){
        socket.emit("EMERG", {srcId: "123456", dstId: current_channel});
    }
    async function startRecording() {
        try {
            const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
            mediaRecorder = new MediaRecorder(stream);
            mediaRecorder.ondataavailable = function (event) {
                audioChunks.push(event.data);
                if (mediaRecorder.state === "inactive") {
                    let audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
                    audioChunks = [];
                    socket.emit('sendAudio', audioBlob);
                }
            };
            mediaRecorder.start();
        } catch (err) {
            console.error("Error accessing microphone:", err);
        }
    }

    if (mediaStream) {
        mediaStream.getTracks().forEach(track => track.stop());
    }
</script>
</body>
<footer>
    <div style="text-align: center;">
        <b>Written by Caleb, KO4UYJ</b>
    </div>
</footer>
</html>

