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

//npm imports
const {validationResult, matchedData} = require('express-validator');

//local imports
const {exceptionHandler, errorHandler} = require('../../../utils/loggerUtils');
const permissionModel = require('../../../schemas/permissionSchema');

//api permissions functions
module.exports.get = async function(req, res){
    try{
        var perms = await permissionModel.getPerms();

        res.status(200);
        return res.send(perms);
    }catch(err){
        return exceptionHandler(res, err);
    }
}

module.exports.post = async function(req, res){
    try{
        //check for validation errors
        const validResult = validationResult(req);

        //if none
        if(validResult.isEmpty()){
            //grab validated/sanatized data
            const {permissionsMap, channelPermissionsMap} = matchedData(req);
            const perms = await permissionModel.getPerms();
            var permError = false;

            //If we're updating normal perms
            if(permissionsMap){
                //For each permission submitted
                Object.keys(permissionsMap).forEach((perm) => {
                    //Check to make sure no one is jumping perms (this should be admins only, but just in-case)
                    //Setting a boolean inside of an if statement seems fucked, until you realize it won't set it back false on the next loop :P
                    if(permissionModel.rankToNum(perms[perm]) > permissionModel.rankToNum(req.session.user.rank) || permissionModel.rankToNum(permissionsMap[perm]) > permissionModel.rankToNum(req.session.user.rank)){
                        permError = true;
                    }

                    //Set permissions in the permissions model
                    perms[perm] = permissionsMap[perm];
                });
            }

            if(channelPermissionsMap){
                //For each permission submitted
                Object.keys(channelPermissionsMap).forEach((perm) => {
                    //Check to make sure no one is jumping perms (this should be admins only, but just in-case)
                    //Setting a boolean inside of an if statement seems fucked, until you realize it won't set it back false on the next loop :P
                    if(permissionModel.rankToNum(perms.channelOverrides[perm]) > permissionModel.rankToNum(req.session.user.rank) || permissionModel.rankToNum(channelPermissionsMap[perm]) > permissionModel.rankToNum(req.session.user.rank)){
                        permError = true;
                    }

                    //Set permissions in the permissions model
                    perms.channelOverrides[perm] = channelPermissionsMap[perm];
                });
            }

            //Flip our shit if something's wrong.
            if(permError){
                return errorHandler(res, "New rank must be equal to or below that of the user changing it.", 'Unauthorized', 401);
            }

            await perms.save();

            //Cleanup return object
            var returnObj = perms.toObject();

            delete returnObj._id
            delete returnObj.channelOverrides._id
            delete returnObj.__v

            //send successful response
            res.status(200);
            return res.send(returnObj);
            //otherwise scream
        }else{
            res.status(400);
            res.send({errors: validResult.array()})
        }
    }catch(err){
        return exceptionHandler(res, err);
    }
}