/*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/>.*/

//local imports
const flairModel = require('../../schemas/flairSchema');
const permissionModel = require('../../schemas/permissionSchema');

module.exports = class{
    constructor(userDB, chanRank, channel, socket){
        this.id = userDB.id;
        this.user = userDB.user;
        this.rank = userDB.rank;
        this.highLevel = userDB.highLevel;
        this.flair = userDB.flair.name;
        this.chanRank = chanRank;
        this.channel = channel;
        this.sockets = [socket.id];
    }

    socketCrawl(cb){
        //Crawl through user's sockets (lol)
        this.sockets.forEach((sockid) => {
            //get socket based on ID
            const socket = this.channel.server.io.sockets.sockets.get(sockid);
            //Callback with socket
            cb(socket);
        });
    }

    //My brain keeps going back to using dynamic per-user namespaces for this
    //but everytime i look into it I come to the conclusion that it's a bad idea, then I toy with making chans namespaces
    //and using per-user channels for this, but what of gold or mod-only features? or games?
    //No matter what it'd probably end up hacky, as namespaces where meant for splitting app logic not user comms (like rooms).
    //at the end of the day there has to be some penance for decent multi-session handling on-top of a library that doesn't do it.
    //Having to crawl through these sockets is that. Because the other ways seem more gross somehow.
    emit(eventName, args){
        this.socketCrawl((socket)=>{socket.emit(eventName, args)});
    }

    //generic disconnect function, defaults to kick
    disconnect(reason, type = "Disconnected"){
        this.emit("kick",{type, reason});
        this.socketCrawl((socket)=>{socket.disconnect()});
    }

    async sendClientMetadata(){
        //Get flairList from DB and setup flairList array
        const flairListDB = await flairModel.find({});
        var flairList = [];

        //Setup our userObj
        const userObj = {
            id: this.id,
            user: this.user,
            rank: this.rank,
            chanRank: this.chanRank,
            highLevel: this.highLevel,
            flair: this.flair
        }

        //For each flair listed in the Database
        flairListDB.forEach((flair)=>{
            //Check if the user has permission to use the current flair
            if(permissionModel.rankToNum(flair.rank) <= permissionModel.rankToNum(this.rank)){
                //If so push a light version of the flair object into our final flair list
                flairList.push({
                    name: flair.name,
                    displayName: flair.displayName
                });
            }
        });

        //Send off the metadata to our user's clients
        this.emit("clientMetadata", {user: userObj, flairList});
    }

    updateFlair(flair){
        this.flair = flair;

        this.channel.broadcastUserList();
        this.sendClientMetadata();
    }

    updateHighLevel(highLevel){
        this.highLevel = highLevel;

        //TODO: show high-level in userlist
        this.channel.broadcastUserList();
        this.sendClientMetadata();
    }
}