/**
 * terminal page HTML template for wssshd
 *
 * Copyright (C) 2024 Stefy Lanza <stefy@nexlab.net> and SexHack.me
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef TERMINAL_PAGE_H
#define TERMINAL_PAGE_H

// terminal page HTML template
static const char *terminal_page_html =
"<!DOCTYPE html>\n"
"<html lang=\"en\">\n"
"<head>\n"
"    <meta charset=\"UTF-8\">\n"
"    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
"    <title>Terminal - %s</title>\n"
"    <link rel=\"icon\" href=\"/favicon.ico\" type=\"image/x-icon\">\n"
"    <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css\" rel=\"stylesheet\">\n"
"    <link href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\" rel=\"stylesheet\">\n"
"    <link rel=\"stylesheet\" href=\"https://unpkg.com/xterm@5.3.0/css/xterm.css\">\n"
"    <script src=\"/xterm.js\"></script>\n"
"    <script src=\"/xterm-addon-fit.js\"></script>\n"
"    <script>\n"
"        // Ensure libraries are loaded\n"
"        function checkLibraries() {\n"
"            if (typeof Terminal === 'undefined') {\n"
"                console.error('Terminal not loaded from CDN');\n"
"                return false;\n"
"            }\n"
"            if (typeof FitAddon === 'undefined') {\n"
"                console.error('FitAddon not loaded from CDN');\n"
"                return false;\n"
"            }\n"
"            console.log('All xterm libraries loaded successfully');\n"
"            return true;\n"
"        }\n"
"\n"
"        // Check immediately and after a delay\n"
"        if (!checkLibraries()) {\n"
"            setTimeout(checkLibraries, 1000);\n"
"        }\n"
"    </script>\n"
"    <style>\n"
"        .navbar-brand {\n"
"            font-weight: bold;\n"
"        }\n"
"        .client-card {\n"
"            transition: transform 0.2s;\n"
"        }\n"
"        .client-card:hover {\n"
"            transform: translateY(-2px);\n"
"            box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n"
"        }\n"
"        .terminal-container {\n"
"            background-color: #1e1e1e;\n"
"            color: #f8f8f2;\n"
"            font-family: 'Courier New', monospace;\n"
"            border-radius: 8px;\n"
"            height: calc(100vh - 200px);\n"
"            min-height: 400px;\n"
"            overflow: hidden;\n"
"            position: relative;\n"
"        }\n"
"        .terminal-input {\n"
"            background: transparent;\n"
"            border: none;\n"
"            color: #f8f8f2;\n"
"            font-family: 'Courier New', monospace;\n"
"            width: 100%;\n"
"            outline: none;\n"
"        }\n"
"        .terminal-input:focus {\n"
"            box-shadow: none;\n"
"        }\n"
"        /* GNOME-like window decorations */\n"
"        .terminal-window {\n"
"            border: 1px solid #ccc;\n"
"            border-radius: 8px;\n"
"            overflow: hidden;\n"
"            box-shadow: 0 2px 10px rgba(0,0,0,0.2);\n"
"        }\n"
"        .window-titlebar {\n"
"            background: linear-gradient(to bottom, #f0f0f0, #e0e0e0);\n"
"            border-bottom: 1px solid #ccc;\n"
"            padding: 4px 8px;\n"
"            display: flex;\n"
"            justify-content: space-between;\n"
"            align-items: center;\n"
"            height: 32px;\n"
"        }\n"
"        .window-title {\n"
"            font-weight: bold;\n"
"            color: #333;\n"
"            font-size: 14px;\n"
"        }\n"
"        .window-controls {\n"
"            display: flex;\n"
"            align-items: center;\n"
"            gap: 4px;\n"
"        }\n"
"        .window-btn {\n"
"            width: 24px;\n"
"            height: 24px;\n"
"            border: none;\n"
"            border-radius: 50%;\n"
"            display: flex;\n"
"            align-items: center;\n"
"            justify-content: center;\n"
"            font-size: 14px;\n"
"            font-weight: bold;\n"
"            cursor: pointer;\n"
"            transition: all 0.2s;\n"
"        }\n"
"        .window-btn:hover {\n"
"            transform: scale(1.1);\n"
"        }\n"
"        .close-btn {\n"
"            background: #ff605c;\n"
"            color: white;\n"
"        }\n"
"        .close-btn:hover {\n"
"            background: #ff403c;\n"
"        }\n"
"        .maximize-btn {\n"
"            background: #28ca42;\n"
"            color: white;\n"
"        }\n"
"        .maximize-btn:hover {\n"
"            background: #24b83a;\n"
"        }\n"
"        .minimize-btn {\n"
"            background: #ffbd44;\n"
"            color: white;\n"
"            display: none; /* Hidden by default, shown in fullscreen */\n"
"        }\n"
"        .minimize-btn:hover {\n"
"            background: #ffad2c;\n"
"        }\n"
"        .window-content {\n"
"            background: #1e1e1e;\n"
"            padding: 8px;\n"
"        }\n"
"        /* Fullscreen styles */\n"
"        .terminal-window.fullscreen {\n"
"            position: fixed;\n"
"            top: 0;\n"
"            left: 0;\n"
"            width: 100vw;\n"
"            height: 100vh;\n"
"            border: none;\n"
"            border-radius: 0;\n"
"            z-index: 9999;\n"
"        }\n"
"        .terminal-window.fullscreen .terminal-container {\n"
"            height: calc(100vh - 40px) !important;\n"
"            min-height: calc(100vh - 40px) !important;\n"
"        }\n"
"        .terminal-window.fullscreen .minimize-btn {\n"
"            display: flex;\n"
"        }\n"
"    </style>\n"
"</head>\n"
"<body>\n"
"<nav class=\"navbar navbar-expand-lg navbar-dark bg-primary\">\n"
"<div class=\"container\">\n"
"<a class=\"navbar-brand\" href=\"/\">\n"
"<i class=\"fas fa-terminal\"></i> WSSSHD control panel</a>\n"
"<div class=\"navbar-nav ms-auto\">\n"
"<span class=\"navbar-text me-3\">SSH Terminal - %s</span>\n"
"<a class=\"nav-link\" href=\"/logout\">Logout</a>\n"
"</div></div></nav>\n"
"<div id=\"notification-area\" class=\"position-fixed top-0 end-0 p-3\" style=\"z-index: 1050;\"></div>\n"
"<div class=\"container mt-4\">\n"
"<div class=\"row\">\n"
"    <div class=\"col-12\">\n"
"        <div class=\"terminal-window\">\n"
"            <div class=\"window-titlebar\">\n"
"                <div class=\"window-title\">\n"
"                    <i class=\"fas fa-terminal\"></i> SSH Terminal - %s\n"
"                </div>\n"
"                <div class=\"window-controls\">\n"
"                    <input type=\"text\" id=\"sshUsername\" class=\"form-control form-control-sm d-inline-block w-auto me-2\" placeholder=\"Username\" value=\"root\" style=\"height: 24px; font-size: 12px; border: none; background: rgba(255,255,255,0.1); color: white;\">\n"
"                    <button id=\"connectBtn\" class=\"btn btn-success btn-sm me-1\" style=\"height: 24px; font-size: 12px; padding: 0 8px;\">\n"
"                        <i class=\"fas fa-play\"></i> Connect\n"
"                    </button>\n"
"                    <button id=\"disconnectBtn\" class=\"btn btn-danger btn-sm me-1\" disabled style=\"height: 24px; font-size: 12px; padding: 0 8px;\">\n"
"                        <i class=\"fas fa-stop\"></i> Disconnect\n"
"                    </button>\n"
"                    <button class=\"window-btn minimize-btn\" title=\"Exit Fullscreen\">_</button>\n"
"                    <button class=\"window-btn maximize-btn\" title=\"Fullscreen\"><span class=\"maximize-icon\">□</span></button>\n"
"                    <button class=\"window-btn close-btn\" title=\"Disconnect\">×</button>\n"
"                </div>\n"
"            </div>\n"
"            <div class=\"window-content\">\n"
"                <div id=\"terminal\" class=\"terminal-container w-100\"></div>\n"
"            </div>\n"
"        </div>\n"
"    </div>\n"
"</div>\n"
"</div>\n"
"\n"
"<script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js\"></script>\n"
"<script>\n"
"console.log('Terminal script starting...');\n"
"console.log('xterm available:', typeof Terminal);\n"
"console.log('xterm-fit available:', typeof FitAddon);\n"
"\n"
"let term = null;\n"
"let fitAddon = null;\n"
"let connected = false;\n"
"let requestId = null;\n"
"let websocket = null;\n"
"\n"
"console.log('Terminal page loaded, adding event listeners');\n"
"document.getElementById('connectBtn').addEventListener('click', connect);\n"
"document.getElementById('disconnectBtn').addEventListener('click', disconnect);\n"
"\n"
"// Window control buttons\n"
"document.querySelector('.close-btn').addEventListener('click', disconnect);\n"
"document.querySelector('.maximize-btn').addEventListener('click', toggleFullscreen);\n"
"document.querySelector('.minimize-btn').addEventListener('click', toggleFullscreen);\n"
"console.log('Event listeners added');\n"
"\n"
"// Fullscreen functionality\n"
"function toggleFullscreen() {\n"
"    const terminalWindow = document.querySelector('.terminal-window');\n"
"    const maximizeBtn = document.querySelector('.maximize-btn');\n"
"    const maximizeIcon = maximizeBtn.querySelector('.maximize-icon');\n"
"\n"
"    if (terminalWindow.classList.contains('fullscreen')) {\n"
"        // Exit fullscreen\n"
"        terminalWindow.classList.remove('fullscreen');\n"
"        maximizeIcon.textContent = '□';\n"
"        maximizeBtn.title = 'Fullscreen';\n"
"    } else {\n"
"        // Enter fullscreen\n"
"        terminalWindow.classList.add('fullscreen');\n"
"        maximizeIcon.textContent = '▭'; // Restore icon\n"
"        maximizeBtn.title = 'Exit Fullscreen';\n"
"    }\n"
"\n"
"    // Resize terminal after fullscreen change\n"
"    setTimeout(() => {\n"
"        if (window.fitTerminal) {\n"
"            window.fitTerminal();\n"
"        }\n"
"        // Update backend terminal size if connected\n"
"        if (connected && requestId && fitAddon) {\n"
"            const newDimensions = fitAddon.proposeDimensions();\n"
"            const newCols = newDimensions.cols || 80;\n"
"            const newRows = newDimensions.rows || 24;\n"
"\n"
"            fetch('/terminal/%s/xterm/resize', {\n"
"                method: 'POST',\n"
"                headers: {\n"
"                    'Content-Type': 'application/x-www-form-urlencoded',\n"
"                },\n"
"                body: 'request_id=' + encodeURIComponent(requestId) +\n"
"                      '&cols=' + encodeURIComponent(newCols) +\n"
"                      '&rows=' + encodeURIComponent(newRows)\n"
"            }).catch(error => {\n"
"                console.error('Resize error during fullscreen toggle:', error);\n"
"            });\n"
"        }\n"
"    }, 100);\n"
"}\n"
"\n"
"\n"
"function connect() {\n"
"    console.log('Connect button clicked');\n"
"    console.log('Connect function called');\n"
"    if (typeof Terminal === 'undefined') {\n"
"        alert('xterm.js library failed to load. Please check your internet connection or refresh the page.');\n"
"        return;\n"
"    }\n"
"    const username = document.getElementById('sshUsername').value;\n"
"    console.log('Username value:', username);\n"
"    if (!username) {\n"
"        alert('Please enter a username');\n"
"        return;\n"
"    }\n"
"    console.log('Username validation passed');\n"
"\n"
"    // Initialize xterm with proper configuration\n"
"    if (!term) {\n"
"        term = new Terminal({\n"
"            cursorBlink: true,\n"
"            cursorStyle: 'block',\n"
"            fontSize: 14,\n"
"            fontFamily: 'Monaco, Menlo, \"Ubuntu Mono\", monospace',\n"
"            theme: {\n"
"                background: '#1e1e1e',\n"
"                foreground: '#f8f8f2',\n"
"                cursor: '#f8f8f2',\n"
"                cursorAccent: '#1e1e1e',\n"
"                selection: 'rgba(248, 248, 242, 0.3)'\n"
"            },\n"
"            allowTransparency: true,\n"
"            scrollback: 1000,\n"
"            tabStopWidth: 4,\n"
"            convertEol: true,\n"
"            disableStdin: false,\n"
"            cursorWidth: 2,\n"
"            bellStyle: 'none',\n"
"            rightClickSelectsWord: true,\n"
"            fastScrollModifier: 'alt',\n"
"            fastScrollSensitivity: 5,\n"
"            screenReaderMode: false,\n"
"            macOptionIsMeta: false,\n"
"            macOptionClickForcesSelection: false,\n"
"            minimumContrastRatio: 1\n"
"        });\n"
"        term.open(document.getElementById('terminal'));\n"
"\n"
"        // Load fit addon\n"
"        try {\n"
"            if (typeof FitAddon !== 'undefined') {\n"
"                fitAddon = new FitAddon.FitAddon();\n"
"                term.loadAddon(fitAddon);\n"
"                console.log('FitAddon loaded successfully');\n"
"            } else {\n"
"                console.error('FitAddon is not available');\n"
"                throw new Error('FitAddon not loaded');\n"
"            }\n"
"        } catch (e) {\n"
"            console.error('Failed to load FitAddon:', e);\n"
"            term.write('Warning: Terminal auto-resizing not available\\r\\n');\n"
"            // Continue without fit addon - terminal will still work\n"
"        }\n"
"\n"
"        // Initial fit after a short delay to ensure DOM is ready\n"
"        setTimeout(() => {\n"
"            window.fitTerminal();\n"
"            // Calculate dimensions after initial fit\n"
"            let initialDimensions = { cols: 80, rows: 24 };\n"
"            if (fitAddon) {\n"
"                initialDimensions = fitAddon.proposeDimensions();\n"
"            }\n"
"            term._initialCols = initialDimensions.cols || 80;\n"
"            term._initialRows = initialDimensions.rows || 24;\n"
"        }, 100);\n"
"\n"
"        // Fit on window resize and update backend terminal size\n"
"        window.addEventListener('resize', () => {\n"
"            window.fitTerminal();\n"
"            // Update terminal size on backend if connected\n"
"            if (connected && requestId && fitAddon) {\n"
"                const newDimensions = fitAddon.proposeDimensions();\n"
"                const newCols = newDimensions.cols || 80;\n"
"                const newRows = newDimensions.rows || 24;\n"
"\n"
"                fetch('/terminal/%s/xterm/resize', {\n"
"                    method: 'POST',\n"
"                    headers: {\n"
"                        'Content-Type': 'application/x-www-form-urlencoded',\n"
"                    },\n"
"                    body: 'request_id=' + encodeURIComponent(requestId) +\n"
"                          '&cols=' + encodeURIComponent(newCols) +\n"
"                          '&rows=' + encodeURIComponent(newRows)\n"
"                }).catch(error => {\n"
"                    console.error('Resize error:', error);\n"
"                });\n"
"            }\n"
"        });\n"
"\n"
"        term.focus();\n"
"    }\n"
"\n"
"    // Define fitTerminal function globally for fullscreen handling\n"
"    window.fitTerminal = function() {\n"
"        if (fitAddon) {\n"
"            fitAddon.fit();\n"
"        }\n"
"    };\n"
"\n"
"    term.write('Connecting to ' + username + '@%s...\\r\\n');\n"
"\n"
"    connected = true;\n"
"    document.getElementById('connectBtn').disabled = true;\n"
"    document.getElementById('disconnectBtn').disabled = false;\n"
"    document.getElementById('sshUsername').disabled = true;\n"
"\n"
"    // Use calculated dimensions (either from initial fit or current)\n"
"    let cols = term._initialCols || 80;\n"
"    let rows = term._initialRows || 24;\n"
"    if (fitAddon) {\n"
"        const dimensions = fitAddon.proposeDimensions();\n"
"        cols = dimensions.cols || cols;\n"
"        rows = dimensions.rows || rows;\n"
"    }\n"
"\n"
"    // Establish WebSocket connection first\n"
"    const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n"
"    const wsUrl = wsProtocol + '//' + window.location.host + '/terminal/%s/ws';\n"
"    console.log('Connecting WebSocket to:', wsUrl);\n"
"\n"
"    websocket = new WebSocket(wsUrl);\n"
"    websocket.binaryType = 'arraybuffer';\n"
"\n"
"    websocket.onopen = function(event) {\n"
"        console.log('WebSocket connected');\n"
"        term.write('WebSocket connected, establishing terminal...\\r\\n');\n"
"\n"
"        // Now send connect request with terminal dimensions\n"
"        const connectUrl = '/terminal/%s/xterm/connect';\n"
"        console.log('Sending connect request to:', connectUrl);\n"
"\n"
"        fetch(connectUrl, {\n"
"            method: 'POST',\n"
"            headers: {\n"
"                'Content-Type': 'application/x-www-form-urlencoded',\n"
"            },\n"
"            body: 'username=' + encodeURIComponent(username) +\n"
"                  '&cols=' + encodeURIComponent(cols) +\n"
"                  '&rows=' + encodeURIComponent(rows),\n"
"            credentials: 'same-origin'\n"
"        })\n"
"        .then(response => {\n"
"            console.log('Connect response status:', response.status);\n"
"            if (!response.ok) {\n"
"                throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n"
"            }\n"
"            return response.json();\n"
"        })\n"
"        .then(data => {\n"
"            console.log('Connect response data:', data);\n"
"            if (data.request_id) {\n"
"                requestId = data.request_id;\n"
"                if (data.command) {\n"
"                    console.log('Launching command:', data.command);\n"
"                }\n"
"                term.write('Terminal connected successfully!\\r\\n');\n"
"\n"
"                // Send resize with current dimensions to ensure correct sizing\n"
"                if (fitAddon) {\n"
"                    const dimensions = fitAddon.proposeDimensions();\n"
"                    const newCols = dimensions.cols || 80;\n"
"                    const newRows = dimensions.rows || 24;\n"
"                    fetch('/terminal/%s/xterm/resize', {\n"
"                        method: 'POST',\n"
"                        headers: {\n"
"                            'Content-Type': 'application/x-www-form-urlencoded',\n"
"                        },\n"
"                        body: 'request_id=' + encodeURIComponent(requestId) +\n"
"                              '&cols=' + encodeURIComponent(newCols) +\n"
"                              '&rows=' + encodeURIComponent(newRows)\n"
"                    }).catch(error => {\n"
"                        console.error('Initial resize error:', error);\n"
"                    });\n"
"                }\n"
"            } else {\n"
"                term.write('Error: ' + (data.error || 'Unknown error') + '\\r\\n');\n"
"                disconnect();\n"
"            }\n"
"        })\n"
"        .catch(error => {\n"
"            console.error('Terminal connection failed:', error);\n"
"            term.write('Terminal connection failed: ' + error.message + '\\r\\n');\n"
"            disconnect();\n"
"        });\n"
"    };\n"
"\n"
"    websocket.onmessage = function(event) {\n"
"        console.log('WebSocket message received:', event.data);\n"
"        if (typeof event.data === 'string') {\n"
"            // JSON message (like session ended)\n"
"            try {\n"
"                const data = JSON.parse(event.data);\n"
"                if (data.ended) {\n"
"                    console.log('Session ended');\n"
"                    disconnect();\n"
"                }\n"
"            } catch (e) {\n"
"                console.error('Failed to parse JSON message:', e);\n"
"            }\n"
"        } else {\n"
"            // Binary data (terminal output)\n"
"            term.write(new Uint8Array(event.data));\n"
"        }\n"
"    };\n"
"\n"
"    websocket.onerror = function(error) {\n"
"        console.error('WebSocket error:', error);\n"
"        term.write('WebSocket error occurred\\r\\n');\n"
"        disconnect();\n"
"    };\n"
"\n"
"    websocket.onclose = function(event) {\n"
"        console.log('WebSocket closed:', event.code, event.reason);\n"
"        term.write('Connection closed\\r\\n');\n"
"        disconnect();\n"
"    };\n"
"\n"
"    // Handle input - send all keystrokes to server via WebSocket\n"
"    term.onKey(e => {\n"
"        if (!connected || !websocket || websocket.readyState !== WebSocket.OPEN) return;\n"
"\n"
"        let data = e.key;\n"
"        console.log('Sending input data via WebSocket:', data);\n"
"\n"
"        // Send input data via WebSocket\n"
"        websocket.send(data);\n"
"\n"
"        // Prevent local display of input\n"
"        e.domEvent.preventDefault();\n"
"    });\n"
"}\n"
"\n"
"function disconnect() {\n"
"    connected = false;\n"
"    document.getElementById('connectBtn').disabled = false;\n"
"    document.getElementById('disconnectBtn').disabled = true;\n"
"    document.getElementById('sshUsername').disabled = false;\n"
"\n"
"    if (websocket && websocket.readyState === WebSocket.OPEN) {\n"
"        websocket.close();\n"
"    }\n"
"    websocket = null;\n"
"\n"
"    if (requestId) {\n"
"        fetch('/terminal/%s/xterm/disconnect', {\n"
"            method: 'POST',\n"
"            headers: {\n"
"                'Content-Type': 'application/x-www-form-urlencoded',\n"
"            },\n"
"            body: 'request_id=' + encodeURIComponent(requestId)\n"
"        });\n"
"        requestId = null;\n"
"    }\n"
"\n"
"    if (term) {\n"
"        term.write('\\r\\nDisconnected\\r\\n');\n"
"        setTimeout(() => {\n"
"            location.reload();\n"
"        }, 3000);\n"
"    }\n"
"}\n"
"\n"
"\n"
"// Focus on terminal when connected\n"
"document.addEventListener('keydown', function(e) {\n"
"    if (connected && term) {\n"
"        term.focus();\n"
"    }\n"
"});\n"
"</script>\n"
"</body>\n"
"</html>\n"
;

#endif /* TERMINAL_PAGE_H */
