/**
 * Remote Terminal - WebSocket Edition
 * FIXED: Properly closes WebSocket on page unload to prevent zombie connections
 */

(async function() {
    // Wait for Terminal and FitAddon to load
    while (typeof Terminal === 'undefined' || typeof FitAddon === 'undefined') {
        await new Promise(r => setTimeout(r, 100));
    }
    
    // ========== TERMINAL INITIALIZATION ==========
    
    const term = new Terminal({
        cursorBlink: true, 
        fontSize: 14,
        fontFamily: 'Consolas, "Courier New", monospace',
        theme: { 
            background: '#1e1e1e', 
            foreground: '#cccccc', 
            cursor: '#00ff00' 
        },
        scrollback: 10000,
        convertEol: true
    });
    
    const fitAddon = new FitAddon.FitAddon();
    term.loadAddon(fitAddon);
    term.open(document.getElementById('terminal'));
    
    await new Promise(r => setTimeout(r, 100));
    fitAddon.fit();
    
    // Welcome message
    term.writeln('Terminal initialized. Connecting via WebSocket...');
    term.writeln('Multi-terminal sync: Type in ANY terminal, see in ALL terminals!');
    term.writeln('Tip: Right-click for Copy/Paste menu, or use Ctrl+Shift+C/V');
    
    // ========== WEBSOCKET CONNECTION ==========
    
    let ws = null;
    let reconnectAttempts = 0;
    const maxReconnectAttempts = 10;
    let intentionalClose = false;
    
    function connectWebSocket() {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const wsUrl = `${protocol}//${window.location.host}/ws/terminal`;
        
        ws = new WebSocket(wsUrl);
        
        ws.onopen = () => {
            console.log('WebSocket connected');
            reconnectAttempts = 0;
            term.writeln('\r\n✓ WebSocket connected - terminals synchronized');
        };
        
        ws.onmessage = (event) => {
            try {
                const message = JSON.parse(event.data);
                
                if (message.type === 'terminal_output') {
                    term.write(message.data);
                }
                else if (message.type === 'connection') {
                    console.log('Connection status:', message.status);
                }
                else if (message.type === 'transfer_progress') {
                    console.log('Transfer progress:', message.transfer_id);
                }
                
            } catch (e) {
                console.error('Error processing WebSocket message:', e);
            }
        };
        
        ws.onerror = (error) => {
            console.error('WebSocket error:', error);
        };
        
        // ws.onclose = () => {
        //     console.log('WebSocket closed');
            
        //     // Don't reconnect if this was intentional (page unload)
        //     if (intentionalClose) {
        //         console.log('WebSocket closed intentionally (page unload)');
        //         return;
        //     }
            
        //     term.writeln('\r\n✗ WebSocket disconnected');
            
        //     // Attempt reconnection
        //     if (reconnectAttempts < maxReconnectAttempts) {
        //         reconnectAttempts++;
        //         const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 10000);
        //         term.writeln(`  Reconnecting in ${delay/1000}s... (attempt ${reconnectAttempts}/${maxReconnectAttempts})`);
                
        //         setTimeout(connectWebSocket, delay);
        //     } else {
        //         term.writeln('  Max reconnection attempts reached. Please refresh the page.');
        //     }
        // };


        
        // ws.onclose = (event) => {
        //     console.log('WebSocket closed', event.code, event.reason);

        //     // If the user is navigating away / closing the tab, do nothing special
        //     if (intentionalClose) {
        //         console.log('WebSocket closed intentionally (page unload)');
        //         return;
        //     }

        //     term.writeln('\r\n✗ WebSocket disconnected (server offline)');
        //     term.writeln('  This tab will close automatically in 2 seconds...');

        //     // Try to close the tab – in most browsers this works if the tab
        //     // was opened programmatically (e.g., your Python app launched it).
        //     setTimeout(() => {
        //         try {
        //             window.close();
        //         } catch (e) {
        //             console.warn('Unable to close window programmatically:', e);
        //             // Fallback: at least stop sending input
        //             term.writeln('\r\nYou can now close this browser tab.');
        //         }
        //     }, 2000);
        // };



    ws.onclose = () => {
        console.log("WebSocket closed");

        if (intentionalClose) {
            console.log("Intentional close, ignoring.");
            return;
        }

        term.writeln("\r\n✗ WebSocket disconnected (server offline)");
        
        // Try to close the window, but detect if it fails
        const canClose = window.close(); 

        // If the browser rejected the close request (tab not opened via JS)
        if (!canClose) {
            term.writeln("  Unable to auto-close this tab. Please close manually.");
            // Stop further reconnect attempts or repeated messages
            ws = null;
            return;
        }

        // If close succeeded, do nothing further
        setTimeout(() => {}, 2000);
    };





    }
    
    // FIXED: Close WebSocket when page unloads
    window.addEventListener('beforeunload', () => {
        intentionalClose = true;
        if (ws && ws.readyState === WebSocket.OPEN) {
            console.log('Closing WebSocket due to page unload');
            ws.close();
        }
    });
    
    // FIXED: Force reconnect when tab becomes visible again (handles server restart)
    document.addEventListener('visibilitychange', () => {
        if (!document.hidden && ws && ws.readyState !== WebSocket.OPEN) {
            console.log('Tab became visible with dead connection - forcing reconnect');
            intentionalClose = false;
            reconnectAttempts = 0;
            connectWebSocket();
        }
    });

    // Initial connection
    connectWebSocket();
    
    // ========== USER INPUT HANDLING ==========
    
    term.onData(data => {
        if (ws && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({
                type: 'terminal_input',
                data: data
            }));
        }
    });
    
    // ========== TERMINAL RESIZE ==========
    
    term.onResize(({cols, rows}) => {
        console.log('Terminal resized to:', cols, 'x', rows);
        
        if (ws && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({
                type: 'terminal_resize',
                cols: cols,
                rows: rows
            }));
        }
    });
    
    let resizeTimeout;
    window.addEventListener('resize', () => {
        clearTimeout(resizeTimeout);
        resizeTimeout = setTimeout(() => {
            fitAddon.fit();
        }, 100);
    });
    
    // ========== COPY/PASTE FUNCTIONALITY ==========
    
    const terminalElement = document.getElementById('terminal');
    let contextMenu = null;
    
    function copySelection() {
        const selection = term.getSelection();
        if (selection) {
            navigator.clipboard.writeText(selection)
                .then(() => console.log('Copied to clipboard'))
                .catch(err => console.warn('Copy failed:', err));
        }
    }
    
    function pasteFromClipboard() {
        navigator.clipboard.readText()
            .then(text => {
                if (text) {
                    term.paste(text);
                }
            })
            .catch(err => console.warn('Paste failed:', err));
    }
    
    terminalElement.addEventListener('paste', (e) => {
        e.preventDefault();
        const text = e.clipboardData?.getData('text');
        if (text) {
            term.paste(text);
        }
    });
    
    term.attachCustomKeyEventHandler((event) => {
        const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
        const modKey = isMac ? event.metaKey : event.ctrlKey;
        
        if (event.type !== 'keydown') return true;
        
        if (modKey && event.key.toLowerCase() === 'c') {
            const hasSelection = term.hasSelection();
            
            if (event.shiftKey || hasSelection) {
                copySelection();
                return false;
            } else if (!hasSelection) {
                return true;
            }
        }
        
        if (modKey && event.shiftKey && event.key.toLowerCase() === 'v') {
            pasteFromClipboard();
            return false;
        }
        
        return true;
    });
    
    // ========== CONTEXT MENU ==========
    
    function removeContextMenu() {
        if (contextMenu) {
            contextMenu.remove();
            contextMenu = null;
        }
    }
    
    function showContextMenu(x, y) {
        removeContextMenu();
        
        const hasSelection = term.hasSelection();
        
        contextMenu = document.createElement('div');
        contextMenu.className = 'context-menu';
        contextMenu.style.left = x + 'px';
        contextMenu.style.top = y + 'px';
        
        const copyItem = document.createElement('div');
        copyItem.className = 'context-menu-item' + (hasSelection ? '' : ' disabled');
        copyItem.textContent = 'Copy';
        if (hasSelection) {
            copyItem.onclick = () => {
                copySelection();
                removeContextMenu();
            };
        }
        contextMenu.appendChild(copyItem);
        
        const pasteItem = document.createElement('div');
        pasteItem.className = 'context-menu-item';
        pasteItem.textContent = 'Paste';
        pasteItem.onclick = () => {
            pasteFromClipboard();
            removeContextMenu();
        };
        contextMenu.appendChild(pasteItem);
        
        const separator = document.createElement('div');
        separator.className = 'context-menu-separator';
        contextMenu.appendChild(separator);
        
        const selectAllItem = document.createElement('div');
        selectAllItem.className = 'context-menu-item';
        selectAllItem.textContent = 'Select All';
        selectAllItem.onclick = () => {
            term.selectAll();
            removeContextMenu();
        };
        contextMenu.appendChild(selectAllItem);
        
        const clearItem = document.createElement('div');
        clearItem.className = 'context-menu-item';
        clearItem.textContent = 'Clear Terminal';
        clearItem.onclick = () => {
            term.clear();
            removeContextMenu();
        };
        contextMenu.appendChild(clearItem);
        
        document.body.appendChild(contextMenu);
        
        const rect = contextMenu.getBoundingClientRect();
        if (rect.right > window.innerWidth) {
            contextMenu.style.left = (x - rect.width) + 'px';
        }
        if (rect.bottom > window.innerHeight) {
            contextMenu.style.top = (y - rect.height) + 'px';
        }
    }
    
    terminalElement.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        showContextMenu(e.pageX, e.pageY);
    });
    
    document.addEventListener('click', removeContextMenu);
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            removeContextMenu();
        }
    });
    
    term.focus();
    
})();
