var sessionIdToFollow = null;
let socket = null;
let paused = false;
let usernamesAndProfileIds = new Map();
let userSessions = new Map();
let positionsTracking = new Map(); // To track the positions of users
let repeatingUsers = new Set(); // To keep track of whose messages are being repeated
let repeatedMessages = new Set(); // To keep track of already repeated messages
let logWindow = window.open("", "LogWindow", "width=600,height=400");
logWindow.document.write("<html><head><title>Log Output</title>body { margin-top: 50px; margin-bottom: 50px; padding-bottom: 60px; }</head><body><pre id='log'></pre></body></html>");
init();

const header = logWindow.document.createElement('div');
header.style.position = 'fixed';
header.style.top = '0';
header.style.width = '100%';
header.style.backgroundColor = '#f1f1f1';
header.style.zIndex = '1000';
header.style.padding = '10px';
header.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
logWindow.document.body.appendChild(header);

// Status Indicator
const statusIndicator = logWindow.document.createElement('span');
statusIndicator.innerText = 'Status: Running';
statusIndicator.style.color = 'green';
statusIndicator.style.marginLeft = '10px';
header.appendChild(statusIndicator);

// Existing buttons
const pauseButton = logWindow.document.createElement('button');
pauseButton.innerText = 'Pause';
pauseButton.style.marginRight = '10px';
pauseButton.addEventListener('click', pause);
header.appendChild(pauseButton);

const resumeButton = logWindow.document.createElement('button');
resumeButton.innerText = 'Resume';
resumeButton.style.marginRight = '10px';
resumeButton.addEventListener('click', resume);
header.appendChild(resumeButton);

const initButton = logWindow.document.createElement('button');
initButton.innerText = 'Init';
initButton.addEventListener('click', init);
header.appendChild(initButton);

// Clear Log button
const clearLogButton = logWindow.document.createElement('button');
clearLogButton.innerText = 'Clear Log';
clearLogButton.style.marginRight = '10px';
clearLogButton.addEventListener('click', function() {
    logWindow.document.getElementById('log').innerText = ''; // Clear the log display
});
header.appendChild(clearLogButton);

// Follow dropdown and button
const followDropdown = logWindow.document.createElement('select');
followDropdown.style.marginRight = '10px';
header.appendChild(followDropdown);

const followButton = logWindow.document.createElement('button');
followButton.innerText = 'Follow';
followButton.style.marginRight = '10px';
followButton.addEventListener('click', function() {
    const usernameToFollow = followDropdown.value;
    const profileId = getProfileId(usernameToFollow);
    if (profileId) {
        sessionIdToFollow = userSessions.get(profileId);
        printAlert(`🟡 Now following ${usernameToFollow}`);
    } else {
        printAlert(`🔴 Cannot follow ${usernameToFollow}. User not found.`);
    }
});
header.appendChild(followButton);

// Stop Following button
const stopFollowButton = logWindow.document.createElement('button');
stopFollowButton.innerText = 'Stop Following';
stopFollowButton.addEventListener('click', function() {
    sessionIdToFollow = null; // Clear the session ID to stop following
    printAlert(`🔴 Stopped following.`);
});
header.appendChild(stopFollowButton);

// Repeat dropdown and button
const repeatDropdown = logWindow.document.createElement('select');
repeatDropdown.style.marginRight = '10px';
header.appendChild(repeatDropdown);

const repeatButton = logWindow.document.createElement('button');
repeatButton.innerText = 'Repeat';
repeatButton.style.marginRight = '10px';
repeatButton.addEventListener('click', function() {
    const usernameToRepeat = repeatDropdown.value;
    const profileId = getProfileId(usernameToRepeat);
    if (profileId) {
        if (repeatingUsers.has(profileId)) {
            repeatingUsers.delete(profileId);
            printAlert(`🔴 Stopped repeating messages from ${usernameToRepeat}`);
            repeatedMessages.clear(); // Clear repeated messages on toggling off
        } else {
            repeatingUsers.add(profileId);
            printAlert(`🟢 Now repeating messages from ${usernameToRepeat}`);
        }
    } else {
        printAlert(`🔴 Cannot repeat from ${usernameToRepeat}. User not found.`);
    }
});
header.appendChild(repeatButton);

// To display the chat input
const inputBar = logWindow.document.createElement('div');
inputBar.style.position = 'fixed';
inputBar.style.bottom = '0';
inputBar.style.width = '100%';
inputBar.style.backgroundColor = '#f1f1f1';
inputBar.style.zIndex = '1000';
inputBar.style.padding = '10px';
inputBar.style.boxShadow = '0 -2px 4px rgba(0,0,0,0.1)';
logWindow.document.body.appendChild(inputBar);

const inputField = logWindow.document.createElement('input');
inputField.type = 'text';
inputField.style.width = '80%';
inputField.style.marginRight = '10px';
inputBar.appendChild(inputField);

inputField.addEventListener('keypress', function(event) {
    if (event.key === 'Enter') {
        say(inputField.value);
        inputField.value = '';
    }
});

function updateStatus() {
    statusIndicator.innerText = paused ? 'Status: Paused' : 'Status: Running';
    statusIndicator.style.color = paused ? 'red' : 'green';
}

function init() {
    socket = null;
    printAlert("Initializing...");
    const nativeWebSocket = window.WebSocket;
    window.WebSocket = function (...args) {
        socket = new nativeWebSocket(...args);
        return socket;
    };

    printAlert(`🟡 Searching for websockets. You can now join the Chatroom.`);
    usernamesAndProfileIds.clear();
    userSessions.clear();
    positionsTracking.clear(); // Clear previous positions
    sessionIdToFollow = null; // Reset follow state
    repeatingUsers.clear(); // Clear any currently repeating users
    repeatedMessages.clear(); // Clear previously repeated messages
    checkSockets();
}

function checkSockets() {
    if (socket === null) {
        window.setTimeout(checkSockets, 100);
        printAlert("🟡 No socket found. Retrying...");
    } else {
        printAlert("🟡 Room found. Starting to listen...");
        storeUsernameOnNewJoin(socket);
        runChat(socket);
        setTimeout(() => {
            socket.send(`42["7004",{"position":{"x":-5.86839676,"y":0.03366667,"z":8.124479}}]`);
        }, 5000);
    }
}

function runChat(ws) {
    ws.addEventListener('message', function(event) {
        // Handle PING Interval
        if (/"pingInterval":15000/.test(event.data)) {
            printAlert("🟡 Wrong socket. Looking for a new socket...");
            init();
            return;
        }

        storeUsernameOnSpawn(ws);
        deleteUserOnLeave(ws);

        const messageMatch = /42\["message",\{"messageType":"2001","messageContent":\{"sessionId":(\d+),"profileId":"([^"]+)","message":"([^"]+)"/.exec(event.data);
        const positionMatch = /42\["message",\{"messageType":"7103","messageContent":\{"position":\{"x":(-?\d+\.\d+),"y":(-?\d+\.\d+),"z":(-?\d+\.\d+)\},"sessionId":(\d+)\}\}\]/.exec(event.data);

        // Handling Messages
        if (messageMatch) {
            const messageSessionId = messageMatch[1];
            const profileId = messageMatch[2];
            const message = messageMatch[3];
            const username = usernamesAndProfileIds.get(profileId) || "Unknown";

            printAlert(`${username}: ${message}`);

            // Check if the message is from a user that is in the repeatingUsers set
            if (!paused && repeatingUsers.has(profileId) && message && !repeatedMessages.has(message)) {
                // Send message once without username
                const formattedMessage = message.replace(/^.*?:\s*/, ''); // Remove username part
                ws.send(`42["chatv2:send",{"message":"${formattedMessage}"}]`);
                printAlert(`🔵🗣️  ${username}: ${formattedMessage}`);
                repeatedMessages.add(message); // Mark this message as repeated
            }

            // If following this user, send movement commands to the server
            if (!paused && sessionIdToFollow === messageSessionId) {
                printAlert(`🔵 Following message from ${username}: ${message}`);
            }
        }

        // Handling Position Updates
        if (positionMatch) {
            const x = positionMatch[1];
            const y = positionMatch[2];
            const z = positionMatch[3];
            const followedSessionId = positionMatch[4];

            positionsTracking.set(followedSessionId, { x, y, z });

            // If following this user, send movement commands to the server
            if (sessionIdToFollow === followedSessionId) {
                printAlert(`🔵 Moving to position (${x}, ${y}, ${z}) for following.`);
                ws.send(`42["7003",{"position":{"x":${x},"y":${y},"z":${z}}}]`);
                ws.send(`42["7004",{"position":{"x":${x},"y":${y},"z":${z}}}]`);
            }
        }
    });
}

function printAlert(str) {
    logWindow.document.getElementById('log').innerText += `${new Date().toLocaleTimeString()} - ${str}\n`;
}

function storeUsernameOnSpawn(ws) {
    ws.addEventListener('message', function(event) {
        const match = /42\["message",\{"messageType":"2000","messageContent":\{"success":true,"roomId":"[^"]+","profileId":"[^"]+","sessionId":\d+,"otherUsers":\[(.*?)\]\}\}\]/.exec(event.data);
        if (match) {
            let otherUsers = match[1];
            const userRegex = /\{"profileId":"([^"]+)","sessionId":(\d+),"profileData":\{"name":"([^"]+)"/g;
            let userMatch;
            while ((userMatch = userRegex.exec(otherUsers)) !== null) {
                const profileId = userMatch[1];
                const sessionId = userMatch[2];
                const username = userMatch[3];

                usernamesAndProfileIds.set(profileId, username);
                userSessions.set(profileId, sessionId);
                printAlert(`🟡 Profile ID: ${profileId}, Username: ${username}, Session ID: ${sessionId}`);
                updateFollowDropdown();
                updateRepeatDropdown(); // Update the repeat dropdown as well
            }
        }
    });
}

function storeUsernameOnNewJoin(ws) {
    ws.addEventListener('message', function(event) {
        const match = /42\["message",\{"messageType":"20000","messageContent":\{"profileId":"([^"]+)","sessionId":(\d+),"profileData":\{"name":"([^"]+)"/.exec(event.data);
        if (match) {
            const profileId = match[1];
            const sessionId = match[2];
            const username = match[3];
            if (!usernamesAndProfileIds.has(profileId) || userSessions.get(profileId) !== sessionId) {
                usernamesAndProfileIds.set(profileId, username);
                userSessions.set(profileId, sessionId);
                printAlert(`🟡 New Join - Profile ID: ${profileId}, Username: ${username}, Session ID: ${sessionId}`);
                updateFollowDropdown();
                updateRepeatDropdown(); // Update the repeat dropdown as well
            }
        }
    });
}

function deleteUserOnLeave(ws) {
    ws.addEventListener('message', function(event) {
        const match = /42\["message",\{"messageType":"20090","messageContent":\{"sessionId":(\d+),"profileId":"([^"]+)"\}\}\]/.exec(event.data);
        if (match) {
            const sessionId = match[1];
            const profileId = match[2];
            if (usernamesAndProfileIds.has(profileId)) {
                const username = usernamesAndProfileIds.get(profileId);
                usernamesAndProfileIds.delete(profileId);
                userSessions.delete(profileId);
                printAlert(`🟡 User Left - Profile ID: ${profileId}, Username: ${username}, Session ID: ${sessionId}`);
                updateFollowDropdown();
                updateRepeatDropdown(); // Update the repeat dropdown as well
            }
        }
    });
}

function getProfileId(username) {
    for (let [profileId, name] of usernamesAndProfileIds.entries()) {
        if (name === username) {
            return profileId;
        }
    }
    return null;
}

function getSocket() {
    return socket;
}

function say(message) {
    if (!paused) {
        socket.send(`42["chatv2:send",{"message":"${message}"}]`);
        printAlert(`🔵🗣️ SYSTEM: ${message}`);
    }
}

function pause() {
    paused = true;
    printAlert("🟡 Chat Bot paused");
    updateStatus();
}

function resume() {
    paused = false;
    printAlert("🟡 Chat Bot resumed");
    updateStatus();
}

function updateFollowDropdown() {
    followDropdown.innerHTML = '';
    usernamesAndProfileIds.forEach((username, profileId) => {
        const option = document.createElement('option');
        option.value = username;
        option.innerText = username;
        followDropdown.appendChild(option);
    });
}

function updateRepeatDropdown() {
    repeatDropdown.innerHTML = '';
    usernamesAndProfileIds.forEach((username, profileId) => {
        const option = document.createElement('option');
        option.value = username;
        option.innerText = username;
        repeatDropdown.appendChild(option);
    });
}

setInterval(() => {
    const options = Array.from(followDropdown.options);
    options.forEach(option => {
        if (!usernamesAndProfileIds.has(getProfileId(option.value))) {
            followDropdown.removeChild(option);
        }
    });

    const repeatOptions = Array.from(repeatDropdown.options);
    repeatOptions.forEach(option => {
        if (!usernamesAndProfileIds.has(getProfileId(option.value))) {
            repeatDropdown.removeChild(option);
        }
    });
}, 5000);