/*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 connectedUser = require('./connectedUser');
const flairModel = require('../../schemas/flairSchema');
const permissionModel = require('../../schemas/permissionSchema');

module.exports = class{
    constructor(server, chanDB){
        this.server = server;
        this.name = chanDB.name;
        this.tokeCommands = chanDB.tokeCommands;
        //Keeping these in a map was originally a vestige but it's more preformant than an array or object so :P
        this.userList = new Map();
    }

    async handleConnection(userDB, chanDB, socket){
        //get current user object from the userlist
        var userObj = this.userList.get(userDB.user);
        //get channel rank for current user
        const chanRank = await chanDB.getChannelRankByUserDoc(userDB);

        //If user is already connected
        if(userObj){
            //Add this socket on to the userobject
            userObj.sockets.push(socket.id);
        //If the user is joining the channel
        }else{
            //Grab flair
            await userDB.populate('flair');
            //Set user object
            userObj = new connectedUser(userDB, chanRank, this, socket);
        }

        //Set user entry in userlist
        this.userList.set(userDB.user, userObj);

        //if everything looks good, admit the connection to the channel
        socket.join(socket.chan);

        //Make sure the client receives important client-info before userlist
        //await this.sendClientMetadata(userDB, socket);
        await userObj.sendClientMetadata();

        //Send out the userlist
        this.broadcastUserList(socket.chan);
    }

    handleDisconnect(socket, reason){
        //If we have more than one active connection
        if(this.userList.get(socket.user.user).sockets.length > 1){
            //temporarily store userObj
            var userObj = this.userList.get(socket.user.user);

            //Filter out disconnecting socket from socket list, and set as current socket list for user
            userObj.sockets = userObj.sockets.filter((id) => {
                return id != socket.id;
            });

            //Update the userlist
            this.userList.set(socket.user.user, userObj);
        }else{
            //If this is the last connection for this user, remove them from the userlist
            this.userList.delete(socket.user.user);
        }

        //and send out the filtered list
        this.broadcastUserList(socket.chan);
    }

    broadcastUserList(){
        //Create a userlist object with the tokebot user pre-loaded
        var userList = [{
            user: "Tokebot",
            flair: "classic",
            highLevel: "∞",
        }];
        
        this.userList.forEach((userObj, user) => {
            userList.push({
                user: user,
                flair: userObj.flair,
                highLevel: userObj.highLevel
            });
        });

        this.server.io.in(this.name).emit("userList", userList);
    }
}