import express           from 'express';
import { StatusCodes }   from 'http-status-codes';
import SecurityCheckType from '../types/SecurityCheckType';
import logger            from '../shared/logging/WinstonLogger';
import ApiRequest        from '../types/ApiRequest';
import EnonceManager     from '../managers/EnonceManager';


class SecurityMiddleware {
    // First check if connected then check if at least ONE rule match. It's NOT an AND but it's a OR function.
    check(checkIfConnected: boolean, ...checkTypes: Array<SecurityCheckType>): (req: ApiRequest, res: express.Response, next: express.NextFunction) => void {
        return async (req: ApiRequest, res: express.Response, next: express.NextFunction) => {
            if ( checkIfConnected ) {
                if ( req.session.profile.id === null ) {
                    return req.session.sendResponse(res, StatusCodes.UNAUTHORIZED);
                }
            }

            let isAllowed = checkTypes.length === 0;

            if ( !isAllowed ) {
                for ( let checkType of checkTypes ) {
                    try {
                        switch ( checkType ) {
                            case SecurityCheckType.TEACHING_STAFF:
                                isAllowed = isAllowed || req.session.profile.isTeachingStaff;
                                break;
                            case SecurityCheckType.ENONCE_STAFF:
                                isAllowed = isAllowed || await EnonceManager.isUserAllowedToAccessEnonce(req.boundParams.enonce, req.session.profile);
                                break;
                            case SecurityCheckType.ENONCE_IS_PUBLISHED:
                                isAllowed = isAllowed || req.boundParams.enonce.published;
                                break;
                            default:
                                isAllowed = isAllowed || false;
                                break;
                        }
                    } catch ( e ) {
                        logger.error('Security check failed !!! => ' + e);
                        isAllowed = isAllowed || false;
                    }
                }
            }

            if ( !isAllowed ) {
                return req.session.sendResponse(res, StatusCodes.FORBIDDEN);
            }

            return next();
        };
    }
}


export default new SecurityMiddleware();