/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024  Rainbownapkin and the TTN Community

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.*/

class chatBox{
    constructor(client){
        //Client Object
        this.client = client

        //Booleans
        this.aspectLock = true;

        //clickDragger object
        this.clickDragger = new canopyUXUtils.clickDragger("#chat-panel-drag-handle", "#chat-panel-div");
        
        //Preprocessor objects
        this.commandPreprocessor = new commandPreprocessor(client);
        this.chatPostprocessor = new chatPostprocessor();

        //Element Nodes
        this.chatPanel = document.querySelector("#chat-panel-div");
        this.highSelect = document.querySelector("#chat-panel-high-level-select");
        this.flairSelect = document.querySelector("#chat-panel-flair-select");
        this.chatBuffer = document.querySelector("#chat-panel-buffer-div");
        this.chatPrompt = document.querySelector("#chat-panel-prompt");
        this.settingsIcon = document.querySelector("#chat-panel-settings-icon");
        this.adminIcon = document.querySelector("#chat-panel-admin-icon");
        this.emoteIcon = document.querySelector("#chat-panel-emote-icon");
        this.sendButton = document.querySelector("#chat-panel-send-button");
        //Seems weird to stick this in here, but the split is dictated by chat width :P
        this.aspectLockIcon = document.querySelector("#media-panel-aspect-lock-icon");
        this.hideChatIcon = document.querySelector("#chat-panel-div-hide");
        this.showChatIcon = document.querySelector("#media-panel-show-chat-icon");

        //Setup functions
        this.setupInput();
        this.defineListeners();
        this.sizeToAspect();
    }

    setupInput(){
        //Chat bar
        this.chatPrompt.addEventListener("keydown", this.send.bind(this));
        this.sendButton.addEventListener("click", this.send.bind(this));
        this.settingsIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});
        this.adminIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});
        this.emoteIcon.addEventListener("click", ()=>{this.client.cPanel.setActivePanel(new panelObj)});

        //Header icons
        this.aspectLockIcon.addEventListener("click", this.lockAspect.bind(this));
        this.showChatIcon.addEventListener("click", ()=>{this.toggleUI()});
        this.hideChatIcon.addEventListener("click", ()=>{this.toggleUI()});
        this.highSelect.addEventListener("change", this.setHighLevel.bind(this));
        this.flairSelect.addEventListener("change", this.setFlair.bind(this));

        //Clickdragger/Resize
        this.clickDragger.handle.addEventListener("mousedown", this.unlockAspect.bind(this));
        window.addEventListener("resize", this.resizeAspect.bind(this));
    }

    defineListeners(){
        this.client.socket.on("chatMessage", this.displayChat.bind(this));
        this.client.socket.on("clearChat", this.clearChat.bind(this));
    }

    clearChat(data){
        //If we where passed a user to check
        if(data.user != null){
            var clearedChats = document.querySelectorAll(`.chat-entry-${data.user}`);
        }else{
            var clearedChats = document.querySelectorAll('.chat-entry');
        }

        //For each chat found
        clearedChats.forEach((chat) => {
            //fuckin' nukem!
            chat.remove();
        });
    }

    displayChat(data){
        //Create chat-entry span
        var chatEntry = document.createElement('span');
        chatEntry.classList.add("chat-panel-buffer","chat-entry",`chat-entry-${data.user}`);

        //Create high-level label
        var highLevel = document.createElement('p');
        highLevel.classList.add("chat-panel-buffer","chat-entry-high-level","high-level");
        highLevel.innerHTML = `${data.highLevel}`;
        chatEntry.appendChild(highLevel);

        //Create username label
        var userLabel = document.createElement('p');
        userLabel.classList.add("chat-panel-buffer","chat-entry-username");

        if(data.flair != "classic"){
            var flair = `flair-${data.flair}`;
        }else{
            var flair =  this.client.userList.colorMap.get(data.user);
        }

        //Create color span
        var colorSpan = document.createElement('span');
        colorSpan.classList.add("chat-entry-flair-span", flair);
        colorSpan.innerHTML = `${data.user}`;
        userLabel.innerHTML = `${colorSpan.outerHTML}: `;

        chatEntry.appendChild(userLabel);

        //Create chat body
        var chatBody = document.createElement('p');
        chatBody.classList.add("chat-panel-buffer","chat-entry-body");
        chatBody.innerHTML = data.msg;
        chatEntry.appendChild(chatBody);


        this.chatBuffer.appendChild(this.chatPostprocessor.preprocess(chatEntry, data));

        //Set size to aspect on launch
        this.resizeAspect();
    }

    send(event){
        if((!event || !event.key || event.key == "Enter") && this.chatPrompt.value){
            this.commandPreprocessor.preprocess(this.chatPrompt.value);
            this.chatPrompt.value = "";
        }
    }

    handleClientInfo(data){
        this.updateFlairSelect(data.flairList, data.user.flair);
        this.updateHighSelect(data.user.highLevel);
    }

    setHighLevel(event){
        const highLevel = event.target.value;

        this.client.socket.emit("setHighLevel", {highLevel});
    }

    setFlair(event){
        const flair = event.target.value;

        this.client.socket.emit("setFlair", {flair});
    }

    updateHighSelect(highLevel){
        this.highSelect.value = highLevel;
    }

    updateFlairSelect(flairList, flair){
        //clear current flair select
        this.flairSelect.innerHTML = "";

        //For each flair in flairlist
        flairList.forEach((flair) => {
            //Create an option
            var flairOption = document.createElement('option');
            //Set the name and innerHTML
            flairOption.value = flair.name;
            flairOption.innerHTML = flair.displayName;

            //Append it to the select
            this.flairSelect.appendChild(flairOption);
        });

        //Set the selected flair in the UI
        this.flairSelect.value = flair;
        //Re-style the UI, do this in two seperate steps in-case we're running for the first time and have nothing to replace.
        this.flairSelect.className = this.flairSelect.className.replace(/flair-\S*/, "");
        this.flairSelect.classList.add(`flair-${flair}`);
    }

    lockAspect(event){
        //prevent the user from breaking shit :P
        if(this.chatPanel.style.display != "none"){
            this.aspectLock = true;
            this.aspectLockIcon.style.display = "none";
            this.sizeToAspect();
        }
    }

    unlockAspect(event){
        this.aspectLock = false;
        this.aspectLockIcon.style.display = "inline";
    }

    resizeAspect(event){
        if(this.aspectLock){
            this.sizeToAspect();
        }else{
            this.client.userList.clickDragger.fixCutoff();
        }
    }

    sizeToAspect(){
        if(this.chatPanel.style.display != "none"){
            var targetVidWidth = this.client.player.getRatio() * this.chatPanel.getBoundingClientRect().height;
            const targetChatWidth = window.innerWidth - targetVidWidth;
            //This should be changeable in settings later on, for now it defaults to 20%
            const limit = window.innerWidth * .2;

            //Set width to target or 20vh depending on whether or not we've hit the width limit
            this.chatPanel.style.width = targetChatWidth > limit ? `${targetChatWidth}px` : '20vh';

            //Fix busted layout
            var pageBreak = document.body.scrollWidth - document.body.getBoundingClientRect().width;
            this.chatPanel.style.width = `${this.chatPanel.getBoundingClientRect().width + pageBreak}px`;
            //This sometimes gets called before userList ahs been initiated :p
            if(this.client.userList != null){
                this.client.userList.clickDragger.fixCutoff();
            }
        }
    } 

    toggleUI(show = !this.chatPanel.checkVisibility()){
        if(show){
            this.chatPanel.style.display = "flex";
            this.showChatIcon.style.display = "none";
            this.client.player.hideVideoIcon.style.display = "flex";
            this.client.userList.clickDragger.fixCutoff();
        }else{
            this.chatPanel.style.display = "none";
            this.showChatIcon.style.display = "flex";
            this.client.player.hideVideoIcon.style.display = "none";
        }
    }
}