/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024-2026 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 profileUpdatePrompt{
    constructor(field){
        this.field = field;
        this.contentNode =  document.querySelector(`#profile-${field}-content`);
        this.promptNode = document.querySelector(`#profile-${field}-prompt`);

        if(this.promptNode != null){
            this.setupInput();
        }
    }
    
    setupInput(){
        this.contentNode.addEventListener('click', this.popPrompt.bind(this));
        this.promptNode.addEventListener('keydown', this.closePrompt.bind(this));
    }

    popPrompt(){
        this.promptNode.style.display = 'inline';
        this.promptNode.focus();
    }

    closePrompt(event){
        //Check if we're finished
        const fin = event.key == "Escape" || (event.key == "Enter" && !event.shiftKey);

        //IF we are
        if(fin){
            //Display the prompt
            this.promptNode.style.display = 'none';
        }

        //Return whether or not we're done
        return fin;
    }
}

class profileUpdateTextPrompt extends profileUpdatePrompt{
    constructor(field, fillPrompt = false){
        //call derived constructor
        super(field);

        //Set fill prompt
        this.fillPrompt = fillPrompt;
    }

    popPrompt(){
        //Call derived method
        super.popPrompt();

        //For each line break
        this.contentNode.querySelectorAll('br').forEach((br)=>{
            //Replace the linenreaks with newlines to get the text area to play nice
            br.outerHTML = "\n"
        });

        //If we're filling the prompt
        if(this.fillPrompt){
            //Fill the prompt content and placeholder
            this.promptNode.value = this.contentNode.textContent;
            this.promptNode.placeholder = this.field;
        //otherwise
        }else{
            //Just fill the placeholder
            this.promptNode.placeholder = this.contentNode.textContent;
        }

        //Hide content
        this.contentNode.style.display = 'none';
    }

    async closePrompt(event){
        //Call derived constructor and check if we're finished, assuming we're finished...
        if(super.closePrompt(event)){
            //Display
            this.contentNode.style.display = 'inline-block';

            //If we're not cancelling
            if(event.key == "Enter" && !event.shiftKey){
                //Create empty update object
                let updateObj = {};

                //Fill field
                updateObj[this.field] = this.promptNode.value;

                //Send er' off
                const update = await utils.ajax.updateProfile(updateObj);

                //Fill content from update, make sure to add line breaks for the bio
                this.contentNode.textContent = utils.unescapeEntities(update[this.field].replaceAll('\n','<br>'));
            }
        }
    }
}

class profileUpdateImagePrompt extends profileUpdatePrompt{
    constructor(){
        //call derived constructor
        super('img');
    }

    popPrompt(){
        //Call derived method
        super.popPrompt();

        this.promptNode.placeholder = this.contentNode.src;
    }

    async closePrompt(event){
        //Call derived constructor
        super.closePrompt(event);

        //If we're not cancelling
        if(event.key == "Enter"){
            //Create empty update object
            let updateObj = {};

            //Fill field
            updateObj[this.field] = this.promptNode.value;

            //Send er' off
            const update = await utils.ajax.updateProfile(updateObj);

            //Fill content from update
            this.contentNode.src = update[this.field];
        }
    }
}

class passwordResetPrompt{
    constructor(){
        this.oldPassNode = document.querySelector('#account-settings-password-reset-old');
        this.newPassNode = document.querySelector('#account-settings-password-reset-new');
        this.confirmPassNode = document.querySelector('#account-settings-password-reset-confirm');

        this.setupInput(this.oldPassNode);
        this.setupInput(this.newPassNode);
        this.setupInput(this.confirmPassNode);
    }

    setupInput(node){
        if(node != null){
            node.addEventListener("keydown", this.update.bind(this));
        }
    }

    async update(event){
        var hasVal = (this.oldPassNode.value && this.newPassNode.value && this.confirmPassNode.value);
        if((!event || event.key == "Enter") && hasVal){
            if(this.newPassNode.value == this.confirmPassNode.value){
                const updateObj = {};

                updateObj.passChange = {
                    oldPass: this.oldPassNode.value,
                    newPass: this.newPassNode.value,
                    confirmPass: this.confirmPassNode.value
                };

                const response = await utils.ajax.updateProfile(updateObj);

                if(response != null){
                    //Return user homepage after good pass change, as we've probably been logged out by the server for security.
                    window.location.pathname = '/';
                }
            }
        }
    }
}

class tokeList{
    constructor(){
        this.tokeList = document.querySelector('#profile-tokes');
        this.tokeListLabel = document.querySelector('.profile-toke-count');
        this.tokeListToggleIcon = document.querySelector('#toggle-toke-list');

        this.setupInput();
    }

    setupInput(){
        this.tokeListLabel.addEventListener('click', this.toggleTokeList.bind(this));
    }

    toggleTokeList(){
        if(this.tokeList.style.visibility == "visible"){
            this.tokeList.style.visibility = "collapse";
            this.tokeListToggleIcon.classList.replace("bi-caret-down-fill","bi-caret-left-fill");
        }else{
            this.tokeList.style.visibility = "visible";
            this.tokeListToggleIcon.classList.replace("bi-caret-left-fill","bi-caret-down-fill");
        }
    }
}

class accountSettingsButton{
    constructor(field, popupClass){
        this.deleteLink = document.querySelector(`#account-settings-${field}-button`);
        this.popupClass = popupClass;

        if(this.deleteLink != null){
            this.setupInput();
        }
    }

    setupInput(){
        this.deleteLink.addEventListener("click",this.showPopup.bind(this));
    }

    async showPopup(event){
        this.popup = new this.popupClass();
    }
}

class changeEmailPopup{
    constructor(){
        this.popup = new canopyUXUtils.popup("changeEmail", true, this.asyncConstructor.bind(this));
    }

    asyncConstructor(){
        this.emailPrompt = document.querySelector('#email-change-popup-email');
        this.passPrompt = document.querySelector('#email-change-popup-password');

        this.setupInput();
    }

    setupInput(){
        this.emailPrompt.addEventListener('keydown', this.emailRequest.bind(this));
        this.passPrompt.addEventListener('keydown', this.emailRequest.bind(this));
    }

    async emailRequest(event){
        if(event.key == "Enter"){
            await utils.ajax.requestEmailChange(this.emailPrompt.value, this.passPrompt.value); 
        }
    }
}

class changePasswordPopup{
    constructor(){
        this.popup = new canopyUXUtils.popup("changePassword", true, this.asyncConstructor.bind(this));
    }

    asyncConstructor(){
        this.oldPassPrompt = document.querySelector('#password-change-popup-old-password');
        this.newPassPrompt = document.querySelector('#password-change-popup-new-password');
        this.confirmPassPrompt = document.querySelector('#password-change-popup-confirm-new-password');

        this.setupInput();
    }

    setupInput(){
        this.oldPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
        this.newPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
        this.confirmPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
    }

    async emailRequest(event){
        if(event.key == "Enter"){
            const updateObj = {};

            updateObj.passChange = {
                oldPass: this.oldPassPrompt.value,
                newPass: this.newPassPrompt.value,
                confirmPass: this.confirmPassPrompt.value
            };

            const response = await utils.ajax.updateProfile(updateObj);

            if(response != null){
                //Return user homepage after good pass change, as we've probably been logged out by the server for security.
                window.location.pathname = '/';
            }
        }
    }
}

class deleteAccountPopup{
    constructor(){
        this.popup = new canopyUXUtils.popup("nukeUser", true, this.asyncConstructor.bind(this));
    }

    asyncConstructor(){
        this.passwordPrompt = document.querySelector("#delete-account-popup-password");

        this.setupInput();
    }

    setupInput(){
        this.passwordPrompt.addEventListener("keydown", this.nukeAccount.bind(this));
    }

    async nukeAccount(event){
        if(event.key == "Enter"){
            await utils.ajax.deleteAccount(event.target.value); 
        }
    }
}

//Object Instantiation
const imgPrompt = new profileUpdateImagePrompt();
const pronounsPrompt = new profileUpdateTextPrompt('pronouns');
const signaturePrompt = new profileUpdateTextPrompt('signature');
const bioPrompt = new profileUpdateTextPrompt('bio', true);
const profileTokeList = new tokeList();
const accountEmailChange = new accountSettingsButton('update-email', changeEmailPopup);
const accountPasswordChange = new accountSettingsButton('change-password', changePasswordPopup);
const accountDeleteButton = new accountSettingsButton('delete', deleteAccountPopup);