let localStream;
let peerConnections = {};
let username = '';
let isVideoEnabled = true;
let isAudioEnabled = true;
let isSelfViewVisible = false;

// 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');

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

// ICE servers configuration for WebRTC
const iceServers = {
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
        { urls: 'stun:stun1.l.google.com:19302' }
    ]
};

// 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;
    }
    
    username = inputUsername;
    selfViewUsername.textContent = username;
    
    try {
        // Get user media
        localStream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
        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();
        
    } 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() {
    socket = io('https://localhost:3000', {
        secure: true,
        rejectUnauthorized: false // For self-signed certificates in development
    });
    
    setupSocketListeners();
}

// 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);
    });
}

// WebRTC functions
function createPeerConnection(userId, shouldCreateOffer = false, remoteUsername = null) {
    const peerConnection = new RTCPeerConnection(iceServers);
    peerConnections[userId] = {
        pc: peerConnection,
        username: remoteUsername
    };

    // 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 {
        const offer = await peerConnection.createOffer();
        await peerConnection.setLocalDescription(offer);
        
        socket.emit('offer', {
            offer: offer,
            target_id: userId
        });
        console.log('Offer sent to:', userId);
    } catch (error) {
        console.error('Error creating offer:', error);
    }
}

async function handleOffer(data) {
    try {
        const 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 {
        const peerConnectionObj = peerConnections[data.target_id] || peerConnections[Object.keys(peerConnections)[0]];
        if (peerConnectionObj && data.candidate) {
            await peerConnectionObj.pc.addIceCandidate(data.candidate);
            console.log('ICE candidate added');
        }
    } catch (error) {
        console.error('Error handling ICE candidate:', error);
    }
}

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

    const remoteVideoContainer = document.createElement('div');
    remoteVideoContainer.className = 'remoteVideoContainer';
    remoteVideoContainer.id = userId;

    const remoteVideo = document.createElement('video');
    remoteVideo.className = 'remoteVideo';
    remoteVideo.autoplay = true;
    remoteVideo.srcObject = stream;
    remoteVideoContainer.appendChild(remoteVideo);

    const usernameElement = document.createElement('div');
    usernameElement.className = 'remoteUsername';
    usernameElement.textContent = `${remoteUsername || `user_${userId.substring(0, 8)}`}`;
    remoteVideoContainer.appendChild(usernameElement);

    remoteVideos.appendChild(remoteVideoContainer);
}

// 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) {
    const videoContainer = document.getElementById(userId);
    if (videoContainer) {
        videoContainer.remove();
    }
    
    const peerConnectionObj = peerConnections[userId];
    if (peerConnectionObj) {
        peerConnectionObj.pc.close();
        delete peerConnections[userId];
    }
}

// Button event handlers
muteButton.addEventListener('click', () => {
    if (localStream) {
        const audioTrack = localStream.getAudioTracks()[0];
        if (audioTrack) {
            audioTrack.enabled = !audioTrack.enabled;
            isAudioEnabled = audioTrack.enabled;
            
            const span = muteButton.querySelector('span');
            
            if (isAudioEnabled) {
                span.textContent = 'mic';
                muteButton.classList.remove('muted');
            } else {
                span.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 span = videoButton.querySelector('span');
            
            // Update local video display visibility
            const localVideoDisplay = document.querySelector('#local-video-display .remoteVideo');
            
            if (isVideoEnabled) {
                span.textContent = 'cam';
                videoButton.classList.remove('disabled');
                if (localVideoDisplay) {
                    localVideoDisplay.style.visibility = 'visible';
                }
                if (selfVideo && isSelfViewVisible) {
                    selfVideo.style.visibility = 'visible';
                }
            } else {
                span.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', () => {
    // Close all peer connections
    Object.values(peerConnections).forEach(pcObj => pcObj.pc.close());
    peerConnections = {};
    
    // Stop local stream
    if (localStream) {
        localStream.getTracks().forEach(track => track.stop());
        localVideo.srcObject = null;
        selfVideo.srcObject = null;
    }
    
    // Remove all videos (including local video display)
    while (remoteVideos.firstChild) {
        remoteVideos.firstChild.remove();
    }
    
    // Disconnect from server
    if (socket) {
        socket.disconnect();
    }
    
    // Reset UI
    chatInterface.classList.add('hidden');
    usernameModal.classList.remove('hidden');
    usernameInput.value = '';
    selfViewContainer.classList.add('hidden');
    isSelfViewVisible = false;
    
    console.log('Left the chat');
});

// Theme toggle functionality
function initTheme() {
    const savedTheme = localStorage.getItem('theme') || 'light';
    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);

// Focus username input on load and initialize theme
document.addEventListener('DOMContentLoaded', () => {
    usernameInput.focus();
    initTheme();
});