html = """
<!DOCTYPE html>
<html>
<head>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <link rel="icon" type="image/x-icon" href="https://media.istockphoto.com/id/1032803298/vector/concept-of-sharing-ideas-between-a-social-network.jpg?s=1024x1024&w=is&k=20&c=flQycFZv11Squs6Q4u5H8Ml21V93bog2ZIm3wmBgnOI=">
    <title>Gemini Live Chat</title>
    <style>
        .user-card {
            background-color: #d1e7dd; /* light green */
            text-align: right;
        }
        .gemini-card {
            background-color: #f8d7da; /* light red/pink */
            text-align: left;
        }
        .chat-message {
            margin: 10px 0;
            padding: 10px;
            border-radius: 10px;
        }
        .loading-animation {
            border: 4px solid #f3f3f3; /* Light grey */
            border-top: 4px solid #3498db; /* Blue */
            border-radius: 50%;
            width: 20px;
            height: 20px;
            animation: spin 2s linear infinite;
            display: inline-block; /* To be next to the message */
            margin-left: 5px;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .controls-container {
            display: flex;
            gap: 10px;
            margin-top: 10px;
            position: relative; /* Make this a positioning context for the loading indicator */
        }

        .controls-container button {
            flex-grow: 1;
        }

        #loading-indicator {
            position: absolute;
            top: 0;
            right: 0;
            margin: 10px; /* Adjust margin to align with the buttons */
        }
    </style>
</head>
<body class="container py-4">
    <h1 class="mb-4 fixed-top bg-light p-3" style="z-index: 1000;">Interacive Learning</h1>

    <div class="card mt-5 pt-3" style="background-color: #FFFFED;">
        <div class="card-body" id="chat-container" style="height: 400px; overflow-y: auto;"></div>
    </div>

    <div class="mt-3 position-relative">

    <div class="d-flex justify-content-between align-items-center mb-2">
    <div>
        <label for="language-select" class="form-label mb-0 me-2">Select Language:</label>
        <select id="language-select" class="form-select d-inline-block w-auto">
            <option value="english" selected>English</option>
            <option value="hindi">Hindi</option>
            <option value="telugu">Telugu</option>
            <option value="bengali">Bengali</option>
            <option value="tamil">Tamil</option>
            <option value="marathi">Marathi</option>
            <option value="gujarati">Gujarati</option>
            <option value="kannada">Kannada</option>
            <option value="malayalam">Malayalam</option>
            <option value="odia">Odia</option>
            <option value="punjabi">Punjabi</option>
            <option value="assamese">Assamese</option>
            <option value="urdu">Urdu</option>
            <option value="sanskrit">Sanskrit</option>
        </select>
    </div>
</div>
        <div style="position: relative; display: flex; align-items: center;">
        <textarea id="message-input" rows="4" class="form-control" placeholder="Type your message..." onkeydown="handleKeyDown(event)"></textarea>
        <!-- File input icon -->
        <label for="file-upload" style="position: absolute; right: 10px; bottom: 10px; cursor: pointer;">
        <i class="fas fa-paperclip" style="font-size: 18px;"></i>

         <!-- Hidden file input -->
        <input type="file" id="file-upload" style="display: none;" accept=".pdf,image/*">
        </div>
        <div class="controls-container">
            <button class="btn btn-secondary" id="pause-resume-button" onclick="toggleSpeech()">
                <i class="fas fa-pause"></i> Pause
            </button>
            <button class="btn btn-danger" id="stop-button" onclick="stopSpeech()">
                <i class="fas fa-stop"></i> Stop
            </button>
            <button class="btn btn-info" id="start-speech-button" onclick="handleSpeechButtonClick()">
                <i class="fas fa-microphone"></i> Start Speech
            </button>
            <button class="btn btn-primary" onclick="sendMessage()">Send</button>
            <div id="loading-indicator" style="display: none;">
                <div class="loading-animation"></div>
            </div>
        </div>
    </div>

   <script>
    // Initialize WebSocket connection
    const ws = new WebSocket(`ws://localhost:8000/ws`);
    const chatContainer = document.getElementById('chat-container');
    const audioPlayer = new Audio();
    const loadingIndicator = document.getElementById('loading-indicator');
    const pauseResumeButton = document.getElementById('pause-resume-button');
    const stopButton = document.getElementById('stop-button');
    const startSpeechButton = document.getElementById('start-speech-button');

    let isSpeaking = false;
    let shouldResume = false;
    let isRecording = false;
    let mediaRecorder;
    let recordedChunks;
    let speechRecognitionActive = false;
    let speechStartTimeout;
    let accessToken = localStorage.getItem('access_token');

    // Helper function to convert base64 to Blob
    function base64toBlob(base64Data, contentType='') {
        const byteCharacters = atob(base64Data);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        const byteArray = new Uint8Array(byteNumbers);
        return new Blob([byteArray], {type: contentType});
    }

    // Handle incoming messages from the server
    ws.onmessage = function(event) {
        const message = event.data.trim();
        if (message.startsWith("Gemini:")) {
            addMessage(message, 'gemini');
            hideLoadingAnimation();
        } else if (message.startsWith("audio:")) {
            const audioBase64 = message.substring(6);
            const audioBlob = base64toBlob(audioBase64, 'audio/mpeg');
            const audioURL = URL.createObjectURL(audioBlob);
            if (!speechRecognitionActive) { // Only play if not actively listening
                audioPlayer.src = audioURL;
                audioPlayer.play();
                isSpeaking = true;
                pauseResumeButton.innerHTML = '<i class="fas fa-pause"></i> Pause';
                audioPlayer.onended = () => {
                    isSpeaking = false;
                    pauseResumeButton.innerHTML = '<i class="fas fa-play"></i> Play';
                    URL.revokeObjectURL(audioURL);
                };
            } else {
                URL.revokeObjectURL(audioURL); // Prevent playing if listening
            }
        } else if (message.startsWith("error:")) {
            console.error("TTS Error:", message.substring(6));
        } else {
            console.log("Received:", message);
        }
        hideLoadingAnimation();
    };

    function toggleSpeech() {
        if (isSpeaking) {
            audioPlayer.pause();
            isSpeaking = false;
            pauseResumeButton.innerHTML = '<i class="fas fa-play"></i> Play';
        } else if (audioPlayer.src) {
            audioPlayer.play();
            isSpeaking = true;
            pauseResumeButton.innerHTML = '<i class="fas fa-pause"></i> Pause';
        }
    }

    function stopSpeech() {
        if (isSpeaking) {
            audioPlayer.pause();
            audioPlayer.currentTime = 0;
            isSpeaking = false;
            showLoadingAnimation(); 
            pauseResumeButton.innerHTML = '<i class="fas fa-play"></i> Play';
        }
    }

    function handleSpeechButtonClick() {
    if (!speechRecognitionActive) {
        speechRecognitionActive = true;
        startSpeechListening();
        startSpeechButton.innerHTML = '<i class="fas fa-microphone-slash"></i> Listening...';
    } else {
        stopSpeechListening();
        speechRecognitionActive = false;
        startSpeechButton.innerHTML = '<i class="fas fa-microphone"></i> Start Speech';
    }
}

async function startSpeechListening() {
    try {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        const audioContext = new (window.AudioContext || window.webkitAudioContext)();
        const source = audioContext.createMediaStreamSource(stream);
        const analyser = audioContext.createAnalyser();
        const processor = audioContext.createScriptProcessor(2048, 1, 1);
        source.connect(analyser);
        analyser.connect(processor);
        processor.connect(audioContext.destination);

        recordedChunks = [];
        mediaRecorder = new MediaRecorder(stream);
        let silenceStart = null;
        const SILENCE_DELAY = 3000; // 3 seconds

        mediaRecorder.ondataavailable = event => {
            if (event.data.size > 0) {
                recordedChunks.push(event.data);
            }
        };

        mediaRecorder.onstop = () => {
            processor.disconnect();
            analyser.disconnect();
            source.disconnect();
            if (recordedChunks.length > 0) {
                const audioBlob = new Blob(recordedChunks, { type: 'audio/webm' });
                const reader = new FileReader();
                reader.onloadend = () => {
                    const selectedLanguage = document.getElementById("language-select").value;
                    const base64Audio = btoa(reader.result);
                    const messageData = {
                            type: "audio",
                            language: selectedLanguage,
                            content: base64Audio
                        };
                    
                    ws.send(JSON.stringify(messageData));
                };
                reader.readAsBinaryString(audioBlob);
            }
            isRecording = false;
            speechRecognitionActive = false;
            startSpeechButton.innerHTML = '<i class="fas fa-microphone"></i> Start Speech';
        };

        processor.onaudioprocess = function () {
            const data = new Uint8Array(analyser.frequencyBinCount);
            analyser.getByteFrequencyData(data);
            const volume = data.reduce((a, b) => a + b) / data.length;

            const THRESHOLD = 10; // adjust this for sensitivity
            if (volume > THRESHOLD) {
                if (!isRecording) {
                    mediaRecorder.start();
                    isRecording = true;
                    console.log("Speech detected, recording started");
                }
                silenceStart = null; // reset silence timer
                if (isSpeaking) {
                    audioPlayer.pause();
                    shouldResume = true;
                }
            } else {
                if (isRecording) {
                    if (!silenceStart) {
                        silenceStart = Date.now();
                    } else if (Date.now() - silenceStart > SILENCE_DELAY) {
                        mediaRecorder.stop();
                        stream.getTracks().forEach(track => track.stop());
                        console.log("Silence detected, recording stopped");
                    }
                }
            }
        };
    } catch (err) {
        console.error("Microphone error:", err);
        speechRecognitionActive = false;
        startSpeechButton.innerHTML = '<i class="fas fa-microphone"></i> Start Speech';
    }
}

    function stopSpeechListening() {
    if (isRecording && mediaRecorder && mediaRecorder.state === 'recording') {
        mediaRecorder.stop();
        isRecording = false;
    }
    speechRecognitionActive = false;
    startSpeechButton.innerHTML = '<i class="fas fa-microphone"></i> Start Speech';
}


    ws.onopen = function() {
        console.log("WebSocket connection opened");
        if (accessToken) {
            ws.send(JSON.stringify({ "access_token": accessToken }));
            }
        
    };

    ws.onclose = function() {
        console.log("WebSocket connection closed");
        hideLoadingAnimation(); // Ensure loading is hidden on close
    };

    ws.onerror = function(error) {
        console.error("WebSocket error:", error);
        hideLoadingAnimation(); // Ensure loading is hidden on error
    };

    // Handle Enter key press
    function handleKeyDown(event) {
        if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault(); // Prevent newline
            sendMessage();
        }
    }

    // Send message function
    function sendMessage() {
        const input = document.getElementById('message-input');
        const text = input.value.trim();
        const selectedLanguage = document.getElementById("language-select").value;


        if (text !== "") {
            // Add user message to the chat
            addMessage(`You: ${text}`, 'user'); // Indicate it's the user's message
            showLoadingAnimation(); // Show loading when sending message

            // Send message via WebSocket
            if (ws.readyState === WebSocket.OPEN) {
                const messageData = {
                type: "text",
                content: text,
                language: selectedLanguage
            };
                ws.send(JSON.stringify(messageData));
            } else {
                console.error("WebSocket is not open. Current state:", ws.readyState);
                hideLoadingAnimation(); // Hide loading if not connected
            }

            // Clear the input field
            input.value = '';
        }
    }

    // Add message to chat container
    function addMessage(message, sender) {
        const messageCard = document.createElement('div');
        messageCard.classList.add('card', 'chat-message');
        messageCard.classList.add(sender === 'user' ? 'user-card' : 'gemini-card');

        const cardBody = document.createElement('div');
        cardBody.classList.add('card-body');
        cardBody.textContent = message;

        messageCard.appendChild(cardBody);
        chatContainer.appendChild(messageCard);
        chatContainer.scrollTop = chatContainer.scrollHeight; // Scroll to bottom
    }

    // Loading animation functions
    function showLoadingAnimation() {
        loadingIndicator.style.display = 'block';
    }

    function hideLoadingAnimation() {
        loadingIndicator.style.display = 'none';
    }


    // Handle file input change event
document.getElementById('file-upload').addEventListener('change', handleFileSelected);

function handleFileSelected(event) {
    const file = event.target.files[0];
    if (!file) return;

    const allowedTypes = ['application/pdf', 'image/png', 'image/jpeg', 'image/jpg'];
    if (!allowedTypes.includes(file.type)) {
        alert("Only PDF and image files are allowed.");
        return;
    }

    const reader = new FileReader();
    reader.onload = function(e) {
        const base64File = e.target.result.split(',')[1]; // remove the data:*/*;base64, part
        const selectedLanguage = document.getElementById("language-select").value;

        const messageData = {
            type: "file",
            fileName: file.name,
            contentType: file.type,
            language: selectedLanguage,
            content: base64File
        };


        if (ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify(messageData));
            showLoadingAnimation();
            addMessage(`You sent a file: ${file.name}`, 'user');
        } else {
            console.error("WebSocket is not open. Current state:", ws.readyState);
        }
    };

    reader.readAsDataURL(file); // read as base64
}


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