<!doctype html>
<html lang="en">
<head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrap demo</title>
        <link rel="stylesheet" href="/static/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/bootstrap-icons.css">

    </head>
    <body> 
        <script src="/static/js/bootstrap.bundle.min.js"></script>
 
        <nav class="navbar navbar-expand-lg bg-body-tertiary">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">Chatter</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarText">
                    <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                        <!--<li class="nav-item">
                            <a class="nav-link active" aria-current="page" href="#">Home</a>
                        </li>-->
                        <li class="nav-item">
                            <!--<a class="nav-link" href="#">Settings</a>-->
                            <a class="btn btn-light" data-bs-toggle="offcanvas" href="#offcanvasTab" role="button" aria-controls="offcanvasTab">Settings</a>
                        </li>
                    </ul>
                    <!--<span class="navbar-text">Navbar text with an inline element</span>-->
                </div>
            </div>
        </nav>

        <div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasTab" aria-labelledby="offcanvasLabel">
            <div class="offcanvas-header">
                <h5 class="offcanvas-title" id="offcanvasLabel">Settings</h5>
                <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
            </div>
            <div class="offcanvas-body">
                
                <form id="settings-form">
                    
                    <!--<label for="text-gen-select">Text Generation Model</label>
                    <select id="text-gen-select" class="form-select" name="text-gen-model" aria-label="Text generation model select">
                        <option value="local">facebook/blenderbot-400M-distill</option>
                        <option value="openai">OpenAI</option>
                    </select>

                    <br>
                    <label for="voice-synth-select">TTS Model</label>
                    <select id="voice-synth-select" class="form-select" name="voice-synth-model" aria-label="Voice synthesis model select">
                        <option value="local">facebook/fastspeech2-en-ljspeech</option>
                        <option value="openai">OpenAI</option>
                    </select>-->

                    <!-- TODO: Add settings, possibly different character types? -->

                    <div class="mb-3">
                        <label for="system-content-text-area" class="form-label">Assistant Description</label>
                        <textarea class="form-control" id="system-content-text-area" name="system-content" rows="3">You are a helpful assistant.</textarea>
                    </div>

                    <br>
                    <button type="submit" class="btn btn-dark">Save</button>
                </form>

            </div>
        </div>

        <div class="container">

            <div class="row mb-3 justify-content-center" style="padding-top: 200px;">
                <div class="col-2">
                    <button id="speak" type="button" class="btn btn-light w-100">Hold to Talk</button>
                </div>
            </div>

            <div class="row justify-content-center text-center">
                <div class="col-3">
                    <i id="reaction-icon" class="bi bi-emoji-neutral" style="font-size: 148px; color: rgb(192, 192, 192);"></i>
                </div>
            </div>

            <div class="row mb-3 justify-content-center text-center">
                <div class="col-3">
                    <p id = "txt-reply"> </p>
                </div>
            </div>

            <div class="row mb-3 justify-content-center">
                <div class="col-3">
                    <audio id="player"></audio>
                </div>
            </div>

        </div>

        <script>

            const pptButton = document.getElementById('speak');
            const player = document.getElementById('player');
            const reactionIcon = document.getElementById('reaction-icon');
            const replyField = document.getElementById('txt-reply');

            var conversation = [];

            document.addEventListener('DOMContentLoaded', function() {
                const settingsForm = document.getElementById('settings-form');

                const settingsDataJSON = localStorage.getItem('settingsData');
                if(settingsDataJSON) {
                    const settingsDataObject = JSON.parse(settingsDataJSON);

                    //TODO: Set form data on load.
                    document.getElementById('system-content-text-area').value = settingsDataObject['system-content'];

                    //document.getElementById('text-gen-select').value = settingsDataObject['text-gen-model'];
                    //document.getElementById('voice-synth-select').value = settingsDataObject['voice-synth-model'];
                }

                settingsForm.addEventListener('submit', function(event){
                    event.preventDefault();

                    const settingsFormData = new FormData(settingsForm);
                    const settingsFormObject = {};
                    settingsFormData.forEach((value, key) => {
                        settingsFormObject[key] = value;
                    });

                    localStorage.setItem('settingsData',JSON.stringify(settingsFormObject));
                    alert('Settings save to local storage.');

                })
            });

            function changeSentiment(sentiment) {
                if(sentiment == 'positive') {
                    reactionIcon.classList.remove('bi-emoji-frown');
                    reactionIcon.classList.remove('bi-emoji-neutral');
                    if(!reactionIcon.classList.contains('bi-emoji-smile')) {
                        reactionIcon.classList.add('bi-emoji-smile');
                    }
                } else if(sentiment == 'negative') {
                    reactionIcon.classList.remove('bi-emoji-smile');
                    reactionIcon.classList.remove('bi-emoji-neutral');
                    if(!reactionIcon.classList.contains('bi-emoji-frown')) {
                        reactionIcon.classList.add('bi-emoji-frown');
                    }
                } else {
                    reactionIcon.classList.remove('bi-emoji-smile');
                    reactionIcon.classList.remove('bi-emoji-frown');
                    if(!reactionIcon.classList.contains('bi-emoji-neutral')) {
                        reactionIcon.classList.add('bi-emoji-neutral');
                    }
                }
            }

            const handleSuccess = async function(stream) {

                var recordedChunks = [];
                const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });

                // Reset recorded data when recorder starts.
                mediaRecorder.addEventListener('start', function() {
                    recordedChunks = [];
                });

                // While recorder is active, add recorded data to an array.
                mediaRecorder.addEventListener('dataavailable', function(e) {
                    if (e.data.size > 0) recordedChunks.push(e.data);
                });

                mediaRecorder.addEventListener('stop', async function() {

                    const audioBlob = new Blob(recordedChunks, { type: 'audio/webm' });
                    if(audioBlob.size < 1000000) {

                        // Will send Blob as multipart/formdata.
                        const convertServiceFormData = new FormData();
                        convertServiceFormData.append('recording', audioBlob, 'recording.webm');

                        // Send a request to convert .webm to .wav type.
                        const response = await fetch('http://localhost:3000/convert', {
                            method: 'POST',
                            body: convertServiceFormData,
                        }).then(function(response) {
                            if (!response.ok) {
                                throw new Error('Response to Conversion Service not OK');
                            }
                            return response.blob();
                        }).then(async function(convertedBlob) {

                            const replyServiceForm = new FormData();
                            replyServiceForm.append('converted', convertedBlob, 'converted.wav');
                            replyServiceForm.append('system-content', document.getElementById('system-content-text-area').value);

                            // Send the .wav file to the Flask application.
                            const response = await fetch('http://localhost:5050/reply', {
                                method: 'POST',
                                body: replyServiceForm,
                            }).then(function(response) {
                                if (!response.ok) {
                                    throw new Error('Reply Service response not OK');
                                }
                                return response.json();
                            }).then(function(data){

                                // Convert encoded data and play it in the browser.
                                var dataUrl = ''
                                if (data['base64_wav']) {
                                    dataUrl = 'data:audio/wav;base64,' + data['base64_wav']
                                } else if (data['base64_mp3']) {
                                    dataUrl = 'data:audio/mp3;base64,' + data['base64_mp3']
                                }

                                if(dataUrl.length > 0) {
                                    fetch(dataUrl)
                                    .then(result => result.blob())
                                    .then(function(replyBlob){
                                        const urlSource = URL.createObjectURL(replyBlob);
                                        player.src = urlSource;
                                        player.play()
                                    })
                                }
                                
                                replyField.innerHTML = "";
                                replyField.innerHTML = data["txt_reply"];

                                // Change the icon based on the estimated sentiment of the reply.
                                changeSentiment(data["reply_sentiment"]);

                                // TODO: Show conversation history.
                                conversation.push(data["txt_asr"])
                                conversation.push(data["txt_reply"])

                            }).catch(function(error){
                                console.error('Problem with your fetch operation to Reply Service:', error);
                            });

                        }).catch(function(error) {
                            console.error('Problem with your fetch operation to Conversion Service:', error);
                        });

                    } else {
                        alert("Recording size limit exceeded.");
                    }

                });

                // TODO: Consider having the system listen continuously instead of stopping & starting.
                pptButton.addEventListener('mousedown', function() {
                    mediaRecorder.start();
                    pptButton.classList.toggle('btn-dark');

                });

                pptButton.addEventListener('mouseup', function() {
                    mediaRecorder.stop();
                    pptButton.classList.toggle('btn-dark');
                });
 
            };

            navigator.mediaDevices
            .getUserMedia({audio: true, video: false})
            .then(handleSuccess);

        </script>
    </body>
</html>