// Configuration variables
let config = {};
let localStream;
let peerConnections = {};
let username = '';
let isVideoEnabled = true;
let isAudioEnabled = true;
let isSelfViewVisible = false;

// Performance monitoring variables
let performanceStats = {};
let qualityMonitoringInterval = null;
let currentQualityProfile = 'medium';

// DOM elements
const usernameModal = document.getElementById('usernameModal');
const usernameForm = document.getElementById('usernameForm');
const usernameInput = document.getElementById('usernameInput');
const chatInterface = document.getElementById('chatInterface');
const localVideo = document.getElementById('localVideo');
const selfVideo = document.getElementById('selfVideo');
const remoteVideos = document.getElementById('remoteVideos');
const muteButton = document.getElementById('muteButton');
const videoButton = document.getElementById('videoButton');
const hangupButton = document.getElementById('hangupButton');
const toggleSelfViewButton = document.getElementById('toggleSelfViewButton');
const selfViewContainer = document.getElementById('selfViewContainer');
const participantCount = document.getElementById('participantCount');
const selfViewUsername = document.getElementById('selfViewUsername');
const themeToggle = document.getElementById('themeToggle');
const connectionQuality = document.getElementById('connectionQuality');
const qualityIndicator = connectionQuality?.querySelector('.quality-indicator');
const qualityText = connectionQuality?.querySelector('.quality-text');

// Chat elements
const chatPanel = document.getElementById('chatPanel');
const chatMessages = document.getElementById('chatMessages');
const chatInput = document.getElementById('chatInput');
const sendButton = document.getElementById('sendButton');
const toggleChatButton = document.getElementById('toggleChatButton');

// Mobile chat elements
const mobileChatToggle = document.getElementById('mobileChatToggle');
const mobileChatOverlay = document.getElementById('mobileChatOverlay');
const mobileChatMessages = document.getElementById('mobileChatMessages');
const mobileChatInput = document.getElementById('mobileChatInput');
const mobileSendButton = document.getElementById('mobileSendButton');
const closeMobileChatButton = document.getElementById('closeMobileChatButton');

// Chat state
let isChatCollapsed = false;
let chatHistory = [];
let isMobileChatOpen = false;
let isMobileDevice = false;

// Initialize Socket.IO connection (but don't connect yet)
let socket;

// Load configuration from config.json
async function loadConfig() {
    try {
        const response = await fetch('/static/config.json');
        config = await response.json();
        console.log('Configuration loaded:', config);
        
        // Apply UI configuration
        if (config.ui) {
            document.getElementById('usernameInput').maxLength = config.ui.maxUsernameLength || 20;
            isSelfViewVisible = config.ui.showSelfViewByDefault || false;
        }
        
        // Apply media configuration
        if (config.media) {
            isVideoEnabled = config.media.defaultVideoEnabled !== false;
            isAudioEnabled = config.media.defaultAudioEnabled !== false;
        }
        
        return config;
    } catch (error) {
        console.error('Failed to load configuration, using defaults:', error);
        // Fallback configuration
        config = {
            server: { port: 3232, ssl: true, rejectUnauthorized: false },
            webrtc: {
                iceServers: [
                    { urls: 'stun:stun.l.google.com:19302' },
                    { urls: 'stun:stun1.l.google.com:19302' }
                ]
            },
            ui: { maxUsernameLength: 20, defaultTheme: 'light', showSelfViewByDefault: false },
            media: { defaultVideoEnabled: true, defaultAudioEnabled: true, videoConstraints: { video: true, audio: true } }
        };
        return config;
    }
}

// Username form submission
usernameForm.addEventListener('submit', async (e) => {
    e.preventDefault();
    const inputUsername = usernameInput.value.trim();
    
    if (inputUsername.length < 1) {
        alert('Please enter a valid username');
        return;
    }
    
    // Load configuration if not already loaded
    if (!config.server) {
        await loadConfig();
    }
    
    username = inputUsername;
    selfViewUsername.textContent = username;
    
    try {
        // Get user media using configuration with mobile optimizations
        let mediaConstraints = config.media?.videoConstraints || {video: true, audio: true};
        
        // Optimize constraints for mobile devices
        if (isMobileDevice) {
            mediaConstraints = {
                video: {
                    width: { ideal: 480, max: 720 },
                    height: { ideal: 360, max: 480 },
                    frameRate: { ideal: 15, max: 24 },
                    facingMode: 'user' // Prefer front camera
                },
                audio: {
                    echoCancellation: true,
                    noiseSuppression: true,
                    autoGainControl: true,
                    sampleRate: 22050 // Lower sample rate for mobile
                }
            };
        }
        
        localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
        localVideo.srcObject = localStream;
        selfVideo.srcObject = localStream;
        
        console.log('Local stream obtained');
        
        // Hide modal and show chat interface
        usernameModal.classList.add('hidden');
        chatInterface.classList.remove('hidden');
        
        // Add your own video to the grid
        addLocalVideoToGrid();
        
        // Initialize Socket.IO connection
        initializeSocket();
        
        // Display welcome message
        displaySystemMessage(`* You have joined #videochat as ${username}`, 'join-message');
        
    } catch (error) {
        console.error('Error accessing media devices:', error);
        alert('Unable to access camera/microphone. Please check your permissions and try again.');
    }
});

// Initialize Socket.IO connection
function initializeSocket() {
    // Use current host and port instead of hardcoded localhost:3000
    const protocol = window.location.protocol === 'https:' ? 'https://' : 'http://';
    const host = window.location.hostname;
    const port = window.location.port || (window.location.protocol === 'https:' ? '443' : '80');
    const serverUrl = `${protocol}${host}:${port}`;
    
    console.log('Connecting to:', serverUrl);
    
    // Use configuration for socket options
    const socketOptions = {
        secure: config.server?.ssl !== false && window.location.protocol === 'https:',
        rejectUnauthorized: config.server?.rejectUnauthorized !== false
    };
    
    socket = io(serverUrl, socketOptions);
    
    setupSocketListeners();
    
    // Start performance monitoring if enabled
    if (config.performance?.enableStats) {
        startPerformanceMonitoring();
    }
}

// Performance monitoring functions
function startPerformanceMonitoring() {
    const interval = config.performance?.statsInterval || 5000;
    
    qualityMonitoringInterval = setInterval(() => {
        monitorConnectionQuality();
    }, interval);
}

function stopPerformanceMonitoring() {
    if (qualityMonitoringInterval) {
        clearInterval(qualityMonitoringInterval);
        qualityMonitoringInterval = null;
    }
}

async function monitorConnectionQuality() {
    for (const [userId, peerConnectionObj] of Object.entries(peerConnections)) {
        try {
            const stats = await peerConnectionObj.pc.getStats();
            const quality = analyzeConnectionStats(stats, userId);
            
            if (quality.shouldAdjust) {
                adjustVideoQuality(userId, quality.recommendedProfile);
            }
        } catch (error) {
            console.warn('Failed to get stats for peer:', userId, error);
        }
    }
    
    // Update connection quality UI
    updateConnectionQualityUI();
}

function analyzeConnectionStats(stats, userId) {
    let bytesReceived = 0;
    let bytesSent = 0;
    let packetsLost = 0;
    let packetsReceived = 0;
    let roundTripTime = 0;
    
    stats.forEach(report => {
        if (report.type === 'inbound-rtp' && report.mediaType === 'video') {
            bytesReceived += report.bytesReceived || 0;
            packetsLost += report.packetsLost || 0;
            packetsReceived += report.packetsReceived || 0;
        } else if (report.type === 'outbound-rtp' && report.mediaType === 'video') {
            bytesSent += report.bytesSent || 0;
        } else if (report.type === 'candidate-pair' && report.state === 'succeeded') {
            roundTripTime = report.currentRoundTripTime || 0;
        }
    });
    
    // Calculate quality metrics
    const packetLossRate = packetsReceived > 0 ? packetsLost / packetsReceived : 0;
    const bandwidth = bytesReceived * 8 / 5; // rough estimate in bps
    
    // Determine recommended profile
    let recommendedProfile = currentQualityProfile;
    
    if (packetLossRate > 0.05 || roundTripTime > 0.3 || bandwidth < 200000) {
        recommendedProfile = 'low';
    } else if (packetLossRate < 0.01 && roundTripTime < 0.1 && bandwidth > 800000) {
        recommendedProfile = 'high';
    } else {
        recommendedProfile = 'medium';
    }
    
    const shouldAdjust = recommendedProfile !== currentQualityProfile;
    
    performanceStats[userId] = {
        packetLossRate,
        bandwidth,
        roundTripTime,
        recommendedProfile,
        timestamp: Date.now()
    };
    
    return { shouldAdjust, recommendedProfile };
}

// Update UI connection quality indicator
function updateConnectionQualityUI() {
    if (!qualityIndicator || !qualityText) return;
    
    const activeConnections = Object.values(performanceStats);
    if (activeConnections.length === 0) {
        qualityIndicator.className = 'quality-indicator good';
        qualityText.textContent = 'Good';
        return;
    }
    
    // Calculate overall quality based on worst performing connection
    let worstPacketLoss = 0;
    let worstRTT = 0;
    let lowestBandwidth = Infinity;
    
    activeConnections.forEach(stats => {
        worstPacketLoss = Math.max(worstPacketLoss, stats.packetLossRate || 0);
        worstRTT = Math.max(worstRTT, stats.roundTripTime || 0);
        lowestBandwidth = Math.min(lowestBandwidth, stats.bandwidth || Infinity);
    });
    
    let qualityClass = 'good';
    let qualityLabel = 'Good';
    
    if (worstPacketLoss > 0.1 || worstRTT > 0.5 || lowestBandwidth < 100000) {
        qualityClass = 'poor';
        qualityLabel = 'Poor';
    } else if (worstPacketLoss > 0.05 || worstRTT > 0.3 || lowestBandwidth < 300000) {
        qualityClass = 'fair';
        qualityLabel = 'Fair';
    }
    
    qualityIndicator.className = `quality-indicator ${qualityClass}`;
    qualityText.textContent = qualityLabel;
    
    // Update tooltip with detailed stats
    const tooltip = `Packet Loss: ${(worstPacketLoss * 100).toFixed(1)}% | RTT: ${(worstRTT * 1000).toFixed(0)}ms | Bandwidth: ${Math.round(lowestBandwidth / 1000)}kbps`;
    connectionQuality.title = tooltip;
}

async function adjustVideoQuality(userId, profileName) {
    if (!config.media?.adaptiveQuality?.enabled) return;
    
    const profile = config.media.adaptiveQuality.profiles[profileName];
    if (!profile) return;
    
    console.log(`Adjusting video quality for ${userId} to ${profileName}:`, profile);
    
    const peerConnectionObj = peerConnections[userId];
    if (!peerConnectionObj) return;
    
    try {
        const sender = peerConnectionObj.pc.getSenders().find(s => 
            s.track && s.track.kind === 'video'
        );
        
        if (sender && sender.track) {
            const params = sender.getParameters();
            
            if (params.encodings && params.encodings.length > 0) {
                params.encodings[0].maxBitrate = profile.bitrate;
                params.encodings[0].maxFramerate = profile.frameRate;
                
                await sender.setParameters(params);
                currentQualityProfile = profileName;
                
                console.log(`Video quality adjusted to ${profileName} for peer ${userId}`);
            }
        }
    } catch (error) {
        console.error('Failed to adjust video quality:', error);
    }
}

// Setup Socket.IO event listeners
function setupSocketListeners() {
    socket.on('connect', () => {
        console.log('Connected to server');
        // Join the room after connecting
        socket.emit('join_room', { username: username });
    });

    socket.on('disconnect', () => {
        console.log('Disconnected from server');
    });

    socket.on('user_joined', (data) => {
        console.log('User joined:', data.id, data.username);
        createPeerConnection(data.id, true, data.username); // This client will create offer
        updateParticipantCount();
    });

    socket.on('existing_users', (data) => {
        console.log('Existing users:', data.users);
        // Connect to existing users (they will create offers to us)
        data.users.forEach(user => {
            createPeerConnection(user.id, false, user.username); // Don't create offer, wait for existing users to offer
        });
        updateParticipantCount();
    });

    socket.on('user_disconnected', (data) => {
        console.log('User disconnected:', data.id);
        handleUserDisconnected(data.id);
        updateParticipantCount();
    });

    socket.on('offer', async (data) => {
        console.log('Received offer from:', data.id);
        await handleOffer(data);
    });

    socket.on('answer', async (data) => {
        console.log('Received answer from:', data.id);
        await handleAnswer(data);
    });

    socket.on('ice_candidate', async (data) => {
        console.log('Received ICE candidate');
        await handleIceCandidate(data);
    });

    // Chat event listeners
    socket.on('chat_message', (data) => {
        displayChatMessage(data.username, data.message, data.timestamp, false);
    });

    socket.on('user_joined_chat', (data) => {
        displaySystemMessage(`* ${data.username} has joined #videochat`, 'join-message');
    });

    socket.on('user_left_chat', (data) => {
        displaySystemMessage(`* ${data.username} has left #videochat`, 'leave-message');
    });
}

// WebRTC functions
function createPeerConnection(userId, shouldCreateOffer = false, remoteUsername = null) {
    // Check connection limit
    if (Object.keys(peerConnections).length >= (config.performance?.maxConnections || 8)) {
        console.warn('Maximum connections reached, cannot create new peer connection');
        return null;
    }
    
    // Use ICE servers from configuration with enhanced settings
    const rtcConfig = {
        iceServers: config.webrtc?.iceServers || [
            { urls: 'stun:stun.l.google.com:19302' },
            { urls: 'stun:stun1.l.google.com:19302' }
        ],
        iceCandidatePoolSize: 10,
        bundlePolicy: 'balanced',
        rtcpMuxPolicy: 'require'
    };
    
    const peerConnection = new RTCPeerConnection(rtcConfig);
    peerConnections[userId] = {
        pc: peerConnection,
        username: remoteUsername,
        created: Date.now(),
        state: 'connecting'
    };
    
    // Set up connection timeout
    setupConnectionTimeout(userId);
    
    // Enhanced connection state monitoring
    peerConnection.onconnectionstatechange = () => {
        const state = peerConnection.connectionState;
        console.log(`Connection state for ${userId}: ${state}`);
        
        if (peerConnections[userId]) {
            peerConnections[userId].state = state;
        }
        
        if (state === 'failed' || state === 'disconnected') {
            console.warn(`Connection ${state} for peer ${userId}, cleaning up...`);
            setTimeout(() => cleanupPeerConnection(userId), 5000); // Grace period
        }
    };
    
    peerConnection.oniceconnectionstatechange = () => {
        const state = peerConnection.iceConnectionState;
        console.log(`ICE connection state for ${userId}: ${state}`);
        
        if (state === 'failed' || state === 'disconnected') {
            console.warn(`ICE connection ${state} for peer ${userId}`);
        }
    };

    // Add local stream to peer connection
    if (localStream) {
        localStream.getTracks().forEach(track => {
            peerConnection.addTrack(track, localStream);
        });
    }

    // Handle remote stream
    peerConnection.ontrack = (event) => {
        console.log('Received remote stream from:', userId);
        addRemoteVideo(userId, event.streams[0], remoteUsername);
    };

    // Handle ICE candidates
    peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
            console.log('Sending ICE candidate');
            socket.emit('ice_candidate', {
                candidate: event.candidate,
                target_id: userId
            });
        }
    };

    // Create offer if this is the initiating peer
    if (shouldCreateOffer) {
        createOffer(peerConnection, userId);
    }

    return peerConnection;
}

async function createOffer(peerConnection, userId) {
    try {
        // Create offer with optimized settings for performance
        const offerOptions = {
            offerToReceiveAudio: true,
            offerToReceiveVideo: true,
            voiceActivityDetection: true,
            iceRestart: false
        };
        
        const offer = await peerConnection.createOffer(offerOptions);
        
        // Optimize SDP for better codec preferences
        const optimizedOffer = optimizeSDP(offer);
        await peerConnection.setLocalDescription(optimizedOffer);
        
        socket.emit('offer', {
            offer: optimizedOffer,
            target_id: userId
        });
        console.log('Offer sent to:', userId);
    } catch (error) {
        console.error('Error creating offer:', error);
    }
}

// Optimize SDP for better performance
function optimizeSDP(sessionDescription) {
    let sdp = sessionDescription.sdp;
    
    // Prefer VP8 over other codecs for better performance
    sdp = preferCodec(sdp, 'video', 'VP8');
    
    // Prefer Opus for audio
    sdp = preferCodec(sdp, 'audio', 'opus');
    
    // Set bandwidth limitations
    const profile = config.media?.adaptiveQuality?.profiles?.[currentQualityProfile];
    if (profile && profile.bitrate) {
        sdp = setBandwidth(sdp, profile.bitrate);
    }
    
    return new RTCSessionDescription({
        type: sessionDescription.type,
        sdp: sdp
    });
}

function preferCodec(sdp, mediaType, codecName) {
    const lines = sdp.split('\r\n');
    const mLineIndex = lines.findIndex(line => line.startsWith(`m=${mediaType}`));
    
    if (mLineIndex === -1) return sdp;
    
    const codecRegex = new RegExp(`a=rtpmap:(\\d+) ${codecName}`, 'i');
    const codecMatch = sdp.match(codecRegex);
    
    if (!codecMatch) return sdp;
    
    const codecPayloadType = codecMatch[1];
    const mLine = lines[mLineIndex];
    const formats = mLine.split(' ');
    const mediaDescription = formats.slice(0, 3).join(' ');
    const payloadTypes = formats.slice(3);
    
    // Move preferred codec to front
    const reorderedPayloadTypes = [codecPayloadType, ...payloadTypes.filter(pt => pt !== codecPayloadType)];
    
    lines[mLineIndex] = `${mediaDescription} ${reorderedPayloadTypes.join(' ')}`;
    
    return lines.join('\r\n');
}

function setBandwidth(sdp, bitrate) {
    // Add bandwidth limitation
    const lines = sdp.split('\r\n');
    const videoMLineIndex = lines.findIndex(line => line.startsWith('m=video'));
    
    if (videoMLineIndex !== -1) {
        const bandwidthLine = `b=AS:${Math.floor(bitrate / 1000)}`;
        lines.splice(videoMLineIndex + 1, 0, bandwidthLine);
    }
    
    return lines.join('\r\n');
}

async function handleOffer(data) {
    try {
        // Check if peer connection already exists, if not create one
        let peerConnection;
        if (peerConnections[data.id]) {
            peerConnection = peerConnections[data.id].pc;
        } else {
            peerConnection = createPeerConnection(data.id, false);
        }
        
        await peerConnection.setRemoteDescription(data.offer);
        const answer = await peerConnection.createAnswer();
        await peerConnection.setLocalDescription(answer);
        
        socket.emit('answer', {
            answer: answer,
            id: data.id
        });
        console.log('Answer sent to:', data.id);
    } catch (error) {
        console.error('Error handling offer:', error);
    }
}

async function handleAnswer(data) {
    try {
        const peerConnectionObj = peerConnections[data.id];
        if (peerConnectionObj) {
            await peerConnectionObj.pc.setRemoteDescription(data.answer);
            console.log('Answer processed from:', data.id);
        }
    } catch (error) {
        console.error('Error handling answer:', error);
    }
}

async function handleIceCandidate(data) {
    try {
        // Find the correct peer connection based on who sent the ICE candidate
        const senderId = data.id || data.senderId;
        const peerConnectionObj = peerConnections[senderId];
        
        if (peerConnectionObj && data.candidate) {
            await peerConnectionObj.pc.addIceCandidate(data.candidate);
            console.log('ICE candidate added for peer:', senderId);
        } else {
            console.warn('No peer connection found for ICE candidate from:', senderId);
        }
    } catch (error) {
        console.error('Error handling ICE candidate:', error);
    }
}

// Video element pool for reuse
const videoElementPool = [];
const maxPoolSize = 10;

function getVideoElement() {
    if (videoElementPool.length > 0) {
        return videoElementPool.pop();
    }
    
    const video = document.createElement('video');
    video.className = 'remoteVideo';
    video.autoplay = true;
    video.playsInline = true; // Important for mobile devices
    video.muted = false;
    
    // Add performance optimizations
    video.setAttribute('playsinline', '');
    video.setAttribute('webkit-playsinline', '');
    
    return video;
}

function returnVideoElement(video) {
    if (videoElementPool.length < maxPoolSize && video) {
        // Clean up the video element
        video.srcObject = null;
        video.removeAttribute('id');
        video.className = 'remoteVideo';
        videoElementPool.push(video);
    }
}

function addRemoteVideo(userId, stream, remoteUsername = null) {
    // Remove existing video if any
    const existingContainer = document.getElementById(userId);
    if (existingContainer) {
        const existingVideo = existingContainer.querySelector('video');
        if (existingVideo) {
            returnVideoElement(existingVideo);
        }
        existingContainer.remove();
    }

    // Create container with optimized DOM operations
    const fragment = document.createDocumentFragment();
    
    const remoteVideoContainer = document.createElement('div');
    remoteVideoContainer.className = 'remoteVideoContainer';
    remoteVideoContainer.id = userId;

    const remoteVideo = getVideoElement();
    remoteVideo.srcObject = stream;
    
    // Add error handling for video playback
    remoteVideo.addEventListener('loadstart', () => {
        console.log(`Video loading started for ${userId}`);
    });
    
    remoteVideo.addEventListener('canplay', () => {
        console.log(`Video ready to play for ${userId}`);
    });
    
    remoteVideo.addEventListener('error', (e) => {
        console.error(`Video error for ${userId}:`, e);
    });
    
    const usernameElement = document.createElement('div');
    usernameElement.className = 'remoteUsername';
    usernameElement.textContent = `${remoteUsername || `user_${userId.substring(0, 8)}`}`;
    
    // Use fragment to minimize DOM reflows
    remoteVideoContainer.appendChild(remoteVideo);
    remoteVideoContainer.appendChild(usernameElement);
    fragment.appendChild(remoteVideoContainer);
    
    // Single DOM insertion
    remoteVideos.appendChild(fragment);
    
    console.log(`Remote video added for ${userId}`);
}

// Add local video to the main grid
function addLocalVideoToGrid() {
    const localVideoContainer = document.createElement('div');
    localVideoContainer.className = 'remoteVideoContainer';
    localVideoContainer.id = 'local-video-display';

    const localVideoDisplay = document.createElement('video');
    localVideoDisplay.className = 'remoteVideo';
    localVideoDisplay.autoplay = true;
    localVideoDisplay.muted = true; // Prevent echo
    localVideoDisplay.srcObject = localStream;
    localVideoDisplay.style.transform = 'scaleX(-1)'; // Mirror effect
    localVideoContainer.appendChild(localVideoDisplay);

    const localUsernameElement = document.createElement('div');
    localUsernameElement.className = 'remoteUsername';
    localUsernameElement.textContent = `${username} (you)`;
    localVideoContainer.appendChild(localUsernameElement);

    remoteVideos.appendChild(localVideoContainer);
}

// Update participant count
function updateParticipantCount() {
    const count = Object.keys(peerConnections).length + 1; // +1 for local user
    participantCount.textContent = `${count} user${count !== 1 ? 's' : ''}`;
}

function handleUserDisconnected(userId) {
    cleanupPeerConnection(userId);
    updateParticipantCount();
}

// Improved cleanup function to prevent memory leaks
function cleanupPeerConnection(userId) {
    console.log('Cleaning up peer connection for:', userId);
    
    // Remove video container
    const videoContainer = document.getElementById(userId);
    if (videoContainer) {
        // Stop all video tracks to free resources
        const video = videoContainer.querySelector('video');
        if (video && video.srcObject) {
            const tracks = video.srcObject.getTracks();
            tracks.forEach(track => track.stop());
            video.srcObject = null;
        }
        videoContainer.remove();
    }
    
    // Clean up peer connection
    const peerConnectionObj = peerConnections[userId];
    if (peerConnectionObj) {
        // Remove all event listeners to prevent memory leaks
        peerConnectionObj.pc.ontrack = null;
        peerConnectionObj.pc.onicecandidate = null;
        peerConnectionObj.pc.onconnectionstatechange = null;
        peerConnectionObj.pc.oniceconnectionstatechange = null;
        
        // Close the connection
        peerConnectionObj.pc.close();
        
        // Remove from our tracking
        delete peerConnections[userId];
        delete performanceStats[userId];
    }
    
    console.log(`Peer connection cleanup completed for ${userId}`);
}

// Enhanced connection timeout handling
function setupConnectionTimeout(userId) {
    const timeout = config.performance?.connectionTimeout || 30000;
    
    setTimeout(() => {
        const peerConnectionObj = peerConnections[userId];
        if (peerConnectionObj && peerConnectionObj.pc.connectionState === 'connecting') {
            console.warn(`Connection timeout for peer ${userId}, cleaning up...`);
            cleanupPeerConnection(userId);
        }
    }, timeout);
}

// Button event handlers
muteButton.addEventListener('click', () => {
    if (localStream) {
        const audioTrack = localStream.getAudioTracks()[0];
        if (audioTrack) {
            audioTrack.enabled = !audioTrack.enabled;
            isAudioEnabled = audioTrack.enabled;
            
            const iconSpan = muteButton.querySelector('.btn-icon');
            const textSpan = muteButton.querySelector('.btn-text');
            
            if (isAudioEnabled) {
                if (iconSpan) iconSpan.textContent = '🎤';
                if (textSpan) textSpan.textContent = 'mic';
                muteButton.classList.remove('muted');
            } else {
                if (iconSpan) iconSpan.textContent = '🔇';
                if (textSpan) textSpan.textContent = 'muted';
                muteButton.classList.add('muted');
            }
        }
    }
});

videoButton.addEventListener('click', () => {
    if (localStream) {
        const videoTrack = localStream.getVideoTracks()[0];
        if (videoTrack) {
            videoTrack.enabled = !videoTrack.enabled;
            isVideoEnabled = videoTrack.enabled;
            
            const iconSpan = videoButton.querySelector('.btn-icon');
            const textSpan = videoButton.querySelector('.btn-text');
            
            // Update local video display visibility
            const localVideoDisplay = document.querySelector('#local-video-display .remoteVideo');
            
            if (isVideoEnabled) {
                if (iconSpan) iconSpan.textContent = '📹';
                if (textSpan) textSpan.textContent = 'cam';
                videoButton.classList.remove('disabled');
                if (localVideoDisplay) {
                    localVideoDisplay.style.visibility = 'visible';
                }
                if (selfVideo && isSelfViewVisible) {
                    selfVideo.style.visibility = 'visible';
                }
            } else {
                if (iconSpan) iconSpan.textContent = '📹';
                if (textSpan) textSpan.textContent = 'nocam';
                videoButton.classList.add('disabled');
                if (localVideoDisplay) {
                    localVideoDisplay.style.visibility = 'hidden';
                }
                if (selfVideo) {
                    selfVideo.style.visibility = 'hidden';
                }
            }
        }
    }
});

toggleSelfViewButton.addEventListener('click', () => {
    isSelfViewVisible = !isSelfViewVisible;
    
    if (isSelfViewVisible) {
        selfViewContainer.classList.remove('hidden');
        toggleSelfViewButton.textContent = '[HIDE]';
        toggleSelfViewButton.title = 'Hide self view';
        // Sync video state with main video
        if (selfVideo && !isVideoEnabled) {
            selfVideo.style.visibility = 'hidden';
        }
    } else {
        selfViewContainer.classList.add('hidden');
        toggleSelfViewButton.textContent = '[VIEW]';
        toggleSelfViewButton.title = 'Show self view';
    }
});

hangupButton.addEventListener('click', () => {
    // Stop performance monitoring
    stopPerformanceMonitoring();
    
    // Clean up all peer connections properly
    Object.keys(peerConnections).forEach(userId => {
        cleanupPeerConnection(userId);
    });
    peerConnections = {};
    performanceStats = {};
    
    // Stop local stream
    if (localStream) {
        localStream.getTracks().forEach(track => {
            track.stop();
            track.enabled = false;
        });
        localVideo.srcObject = null;
        selfVideo.srcObject = null;
        localStream = null;
    }
    
    // Clean up video elements efficiently
    const videoContainers = remoteVideos.querySelectorAll('.remoteVideoContainer');
    videoContainers.forEach(container => {
        const video = container.querySelector('video');
        if (video) {
            returnVideoElement(video);
        }
        container.remove();
    });
    
    // Disconnect from server
    if (socket) {
        socket.disconnect();
        socket = null;
    }
    
    // Reset UI
    chatInterface.classList.add('hidden');
    usernameModal.classList.remove('hidden');
    usernameInput.value = '';
    selfViewContainer.classList.add('hidden');
    isSelfViewVisible = false;
    currentQualityProfile = 'medium';
    
    // Clear chat
    clearChatHistory();
    isChatCollapsed = false;
    if (chatPanel) {
        chatPanel.classList.remove('collapsed');
    }
    
    // Close mobile chat if open
    if (isMobileChatOpen) {
        closeMobileChat();
    }
    
    console.log('Left the chat and cleaned up resources');
});

// Theme toggle functionality
function initTheme() {
    const defaultTheme = config.ui?.defaultTheme || 'light';
    const savedTheme = localStorage.getItem('theme') || defaultTheme;
    document.documentElement.setAttribute('data-theme', savedTheme);
    updateThemeToggleIcon(savedTheme);
}

function toggleTheme() {
    const currentTheme = document.documentElement.getAttribute('data-theme');
    const newTheme = currentTheme === 'light' ? 'dark' : 'light';
    
    document.documentElement.setAttribute('data-theme', newTheme);
    localStorage.setItem('theme', newTheme);
    updateThemeToggleIcon(newTheme);
}

function updateThemeToggleIcon(theme) {
    themeToggle.textContent = theme === 'light' ? '🌙' : '☀️';
}

themeToggle.addEventListener('click', toggleTheme);

// Mobile detection
function detectMobileDevice() {
    isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||
                     window.innerWidth <= 768 ||
                     ('ontouchstart' in window) ||
                     (navigator.maxTouchPoints > 0);
    
    console.log('Mobile device detected:', isMobileDevice);
    
    // Add mobile class to body
    if (isMobileDevice) {
        document.body.classList.add('mobile-device');
    }
    
    return isMobileDevice;
}

// IRC-style Chat Functions
function setupChatEventListeners() {
    // Desktop chat listeners
    if (chatInput && sendButton) {
        chatInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendChatMessage();
            }
        });
        
        sendButton.addEventListener('click', sendChatMessage);
        
        chatInput.addEventListener('focus', () => {
            chatInput.classList.add('focused');
        });

        chatInput.addEventListener('blur', () => {
            chatInput.classList.remove('focused');
        });
    }

    // Desktop toggle
    if (toggleChatButton) {
        toggleChatButton.addEventListener('click', toggleChatPanel);
    }

    // Mobile chat listeners
    if (mobileChatToggle) {
        mobileChatToggle.addEventListener('click', openMobileChat);
    }

    if (closeMobileChatButton) {
        closeMobileChatButton.addEventListener('click', closeMobileChat);
    }

    if (mobileChatInput && mobileSendButton) {
        mobileChatInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMobileChatMessage();
            }
        });
        
        mobileSendButton.addEventListener('click', sendMobileChatMessage);
        
        // Prevent zoom on iOS when focusing input
        if (isMobileDevice && /iPhone|iPad|iPod/i.test(navigator.userAgent)) {
            mobileChatInput.addEventListener('focus', (e) => {
                e.target.style.fontSize = '16px';
            });
            
            mobileChatInput.addEventListener('blur', (e) => {
                e.target.style.fontSize = '';
            });
        }
    }

    // Handle orientation changes
    window.addEventListener('orientationchange', () => {
        setTimeout(() => {
            handleOrientationChange();
        }, 100);
    });

    // Handle window resize for responsive updates
    window.addEventListener('resize', debounce(() => {
        detectMobileDevice();
        handleOrientationChange();
    }, 250));
}

function sendChatMessage() {
    const message = chatInput.value.trim();
    if (!message || !socket) return;

    // Check for IRC-style commands
    if (message.startsWith('/')) {
        handleChatCommand(message);
        chatInput.value = '';
        chatInput.focus();
        return;
    }

    // Display own message immediately
    displayChatMessage(username, message, Date.now(), true);

    // Send to server
    socket.emit('chat_message', {
        username: username,
        message: message,
        timestamp: Date.now()
    });

    // Clear input
    chatInput.value = '';
    chatInput.focus();
}

function handleChatCommand(command) {
    const [cmd, ...args] = command.toLowerCase().split(' ');
    
    switch (cmd) {
        case '/clear':
            clearChatHistory();
            displaySystemMessage('* Chat cleared');
            break;
            
        case '/me':
            const action = args.join(' ');
            if (action) {
                const actionMessage = `* ${username} ${action}`;
                displaySystemMessage(actionMessage, 'system-message');
                socket.emit('chat_message', {
                    username: username,
                    message: `/me ${action}`,
                    timestamp: Date.now()
                });
            }
            break;
            
        case '/help':
            displaySystemMessage('* Available commands:');
            displaySystemMessage('* /clear - Clear chat history');
            displaySystemMessage('* /me <action> - Send action message');
            displaySystemMessage('* /users - List connected users');
            displaySystemMessage('* /time - Show current time');
            break;
            
        case '/users':
            const userCount = Object.keys(peerConnections).length + 1;
            displaySystemMessage(`* Users in #videochat: ${userCount} (including you)`);
            break;
            
        case '/time':
            const now = new Date().toLocaleString();
            displaySystemMessage(`* Current time: ${now}`);
            break;
            
        default:
            displaySystemMessage(`* Unknown command: ${cmd}. Type /help for available commands.`);
    }
}

function displayChatMessage(senderUsername, message, timestamp, isOwnMessage = false) {
    const messageElement = document.createElement('div');
    messageElement.className = `message ${isOwnMessage ? 'own-message' : ''}`;

    const time = new Date(timestamp).toLocaleTimeString('en-US', {
        hour12: false,
        hour: '2-digit',
        minute: '2-digit'
    });

    // Handle /me actions
    if (message.startsWith('/me ')) {
        const action = message.substring(4);
        messageElement.innerHTML = `
            <span class="message-timestamp">[${time}]</span>
            <span class="message-text system-message">* ${senderUsername} ${escapeHtml(action)}</span>
        `;
        messageElement.className = 'message action-message';
    } else {
        messageElement.innerHTML = `
            <span class="message-timestamp">[${time}]</span>
            <span class="message-username">&lt;${senderUsername}&gt;</span>
            <span class="message-text">${escapeHtml(message)}</span>
        `;
    }

    // Add to both desktop and mobile chat containers
    if (chatMessages) {
        chatMessages.appendChild(messageElement);
        scrollChatToBottom();
    }
    
    // Clone message for mobile chat
    if (mobileChatMessages) {
        const mobileMessageElement = messageElement.cloneNode(true);
        mobileChatMessages.appendChild(mobileMessageElement);
        
        if (isMobileChatOpen) {
            scrollMobileChatToBottom();
        }
    }
    
    // Store in history
    chatHistory.push({
        username: senderUsername,
        message: message,
        timestamp: timestamp,
        isOwnMessage: isOwnMessage
    });

    // Limit chat history to prevent memory issues
    if (chatHistory.length > 1000) {
        chatHistory = chatHistory.slice(-500);
        // Remove old DOM elements from both containers
        if (chatMessages && chatMessages.children.length > 500) {
            while (chatMessages.children.length > 500) {
                chatMessages.removeChild(chatMessages.firstChild);
            }
        }
        if (mobileChatMessages && mobileChatMessages.children.length > 500) {
            while (mobileChatMessages.children.length > 500) {
                mobileChatMessages.removeChild(mobileChatMessages.firstChild);
            }
        }
    }
}

function displaySystemMessage(message, className = 'system-message') {
    const messageElement = document.createElement('div');
    messageElement.className = className;
    messageElement.textContent = message;
    
    // Add to both containers
    if (chatMessages) {
        chatMessages.appendChild(messageElement);
        scrollChatToBottom();
    }
    
    if (mobileChatMessages) {
        const mobileMessageElement = messageElement.cloneNode(true);
        mobileChatMessages.appendChild(mobileMessageElement);
        
        if (isMobileChatOpen) {
            scrollMobileChatToBottom();
        }
    }
}

function scrollChatToBottom() {
    chatMessages.scrollTop = chatMessages.scrollHeight;
}

function toggleChatPanel() {
    isChatCollapsed = !isChatCollapsed;
    chatPanel.classList.toggle('collapsed', isChatCollapsed);
    
    if (!isChatCollapsed) {
        // Focus input when expanding
        setTimeout(() => chatInput.focus(), 300);
        scrollChatToBottom();
    }
}

function escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

function clearChatHistory() {
    chatHistory = [];
    const defaultMessages = `
        <div class="system-message">* Now talking in #videochat</div>
        <div class="system-message">* Topic is: Welcome to the video chat room</div>
    `;
    
    if (chatMessages) {
        chatMessages.innerHTML = defaultMessages;
    }
    
    if (mobileChatMessages) {
        mobileChatMessages.innerHTML = defaultMessages;
    }
}

// Mobile-specific chat functions
function openMobileChat() {
    isMobileChatOpen = true;
    mobileChatOverlay.classList.remove('hidden');
    
    // Sync messages from desktop chat
    syncChatMessages();
    
    // Focus input after animation
    setTimeout(() => {
        if (mobileChatInput) {
            mobileChatInput.focus();
        }
        scrollMobileChatToBottom();
    }, 300);
    
    // Prevent body scrolling when chat is open
    document.body.style.overflow = 'hidden';
}

function closeMobileChat() {
    isMobileChatOpen = false;
    mobileChatOverlay.classList.add('hidden');
    
    // Restore body scrolling
    document.body.style.overflow = '';
    
    // Blur input to hide keyboard
    if (mobileChatInput) {
        mobileChatInput.blur();
    }
}

function sendMobileChatMessage() {
    const message = mobileChatInput.value.trim();
    if (!message || !socket) return;

    // Check for IRC-style commands
    if (message.startsWith('/')) {
        handleChatCommand(message);
        mobileChatInput.value = '';
        mobileChatInput.focus();
        return;
    }

    // Display own message immediately
    displayChatMessage(username, message, Date.now(), true);

    // Send to server
    socket.emit('chat_message', {
        username: username,
        message: message,
        timestamp: Date.now()
    });

    // Clear input and maintain focus
    mobileChatInput.value = '';
    mobileChatInput.focus();
}

function syncChatMessages() {
    if (!mobileChatMessages) return;
    
    // Copy all messages from desktop chat to mobile chat
    mobileChatMessages.innerHTML = chatMessages ? chatMessages.innerHTML : '';
    scrollMobileChatToBottom();
}

function scrollMobileChatToBottom() {
    if (mobileChatMessages) {
        mobileChatMessages.scrollTop = mobileChatMessages.scrollHeight;
    }
}

function handleOrientationChange() {
    if (isMobileDevice) {
        // Adjust layout after orientation change
        setTimeout(() => {
            if (isMobileChatOpen) {
                scrollMobileChatToBottom();
            } else {
                scrollChatToBottom();
            }
            
            // Force video layout recalculation
            const videos = document.querySelectorAll('video');
            videos.forEach(video => {
                if (video.srcObject) {
                    video.style.height = 'auto';
                }
            });
        }, 500);
    }
}

// Utility function for debouncing
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// Focus username input on load and initialize theme
document.addEventListener('DOMContentLoaded', async () => {
    await loadConfig();
    detectMobileDevice();
    
    // Only focus input on non-mobile devices to prevent keyboard popup
    if (!isMobileDevice) {
        usernameInput.focus();
    }
    
    initTheme();
    setupChatEventListeners();
});