"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processRequest = processRequest;
const uuid_1 = require("uuid");
const ppath = __importStar(require("path"));
const HotRouteMethod_1 = require("./HotRouteMethod");
const HotHTTPServer_1 = require("./HotHTTPServer");
const HotIO_1 = require("./HotIO");
const HotAPI_1 = require("./HotAPI");
const HotProcessInput_1 = require("./HotProcessInput");
function processRequest(server, logger, route, method, methodName, req, res) {
    return __awaiter(this, void 0, void 0, function* () {
        let hasAuthorization = true;
        let authorizationValue = null;
        let jsonObj = req.body;
        let queryObj = req.query;
        let api = route.connection.api;
        let thisObj = route;
        if (api.executeEventsUsing === HotAPI_1.EventExecutionType.HotAPI)
            thisObj = api;
        if (api.executeEventsUsing === HotAPI_1.EventExecutionType.HotMethod)
            thisObj = method;
        logger.verbose(() => `${req.method} ${methodName}, JSON: ${JSON.stringify(jsonObj)}, Query: ${JSON.stringify(queryObj)}`);
        if (method.onServerAuthorize != null) {
            try {
                let request = new HotRouteMethod_1.ServerRequest({
                    req: req,
                    res: res,
                    bearerToken: "",
                    authorizedValue: authorizationValue,
                    jsonObj: jsonObj,
                    queryObj: queryObj,
                    files: null
                });
                if (req.headers.authorization != null) {
                    request.bearerToken = req.headers.authorization;
                    request.bearerToken = request.bearerToken.substring(7);
                }
                authorizationValue = yield method.onServerAuthorize.call(thisObj, request);
            }
            catch (ex) {
                let statusCode = 401;
                if (ex.statusCode != null)
                    statusCode = ex.statusCode;
                logger.error(`Authorization error ${statusCode}: ${ex.message}`);
                hasAuthorization = false;
                return ({ error: ex.message, errorCode: statusCode });
            }
            if (authorizationValue === undefined)
                hasAuthorization = false;
        }
        else {
            if (route.onAuthorizeUser != null) {
                try {
                    let request = new HotRouteMethod_1.ServerRequest({
                        req: req,
                        res: res,
                        bearerToken: "",
                        authorizedValue: null,
                        jsonObj: jsonObj,
                        queryObj: queryObj,
                        files: null
                    });
                    if (req.headers.authorization != null) {
                        request.bearerToken = req.headers.authorization;
                        request.bearerToken = request.bearerToken.substring(7);
                    }
                    authorizationValue = yield route.onAuthorizeUser(request);
                }
                catch (ex) {
                    let statusCode = 401;
                    if (ex.statusCode != null)
                        statusCode = ex.statusCode;
                    logger.error(`Authorization error ${statusCode}: ${ex.message}`);
                    hasAuthorization = false;
                    return ({ error: ex.message, errorCode: statusCode });
                }
                if (authorizationValue === undefined)
                    hasAuthorization = false;
            }
        }
        logger.verbose(() => `${req.method} ${methodName}, Authorized: ${hasAuthorization}`);
        if (hasAuthorization === true) {
            let uploadedFiles = yield HotHTTPServer_1.HotHTTPServer.getFileUploads(logger, req);
            if (Object.keys(uploadedFiles).length > 0) {
                if (method.type !== HotRouteMethod_1.HotEventMethod.FILE_UPLOAD)
                    return ({ error: `Cannot upload files to a non-file upload method. When registering the route be sure to use HotEventMethod.FILE_UPLOAD.`, errorCode: 400 });
                const hotstaqUploadId = (0, uuid_1.v4)();
                server.uploads[hotstaqUploadId] = {};
                const tempDir = process.env["TEMP_UPLOAD_DIR"] || "./temp/";
                try {
                    yield HotIO_1.HotIO.mkdir(tempDir);
                }
                catch (ex) {
                }
                for (let key in uploadedFiles) {
                    let uploadedFile = uploadedFiles[key][0];
                    const newFilePath = ppath.normalize(`${tempDir}/${uploadedFile.originalFilename}`);
                    yield HotIO_1.HotIO.moveFile(uploadedFile.filepath, newFilePath, { overwrite: true });
                    let uploadedObj = {
                        name: uploadedFile.originalFilename,
                        size: uploadedFile.size,
                        path: newFilePath
                    };
                    server.uploads[hotstaqUploadId][key] = uploadedObj;
                }
                logger.verbose(() => `${req.method} ${methodName}, Upload ID: ${hotstaqUploadId}, Received uploads: ${JSON.stringify(server.uploads[hotstaqUploadId])}`);
                return ({
                    hotstaq: {
                        uploads: {
                            uploadId: hotstaqUploadId
                        }
                    }
                });
            }
            let request = new HotRouteMethod_1.ServerRequest({
                req: req,
                res: res,
                bearerToken: "",
                authorizedValue: authorizationValue,
                jsonObj: jsonObj,
                queryObj: queryObj,
                files: null,
                onClose: null
            });
            res.on("close", () => {
                if (request.onClose != null)
                    request.onClose.call(thisObj, request);
            });
            // The validations have to occur after any possible file uploads.
            if (queryObj != null) {
                if (Object.keys(queryObj).length > 0) {
                    if (method.validateQueryInput != null) {
                        let skipValidation = 0;
                        if (queryObj["hotstaq_skip_validation"] != null)
                            skipValidation = queryObj["hotstaq_skip_validation"];
                        if (skipValidation === 0) {
                            try {
                                if (method.onValidateQueryInput != null)
                                    yield method.onValidateQueryInput.call(thisObj, queryObj);
                                else
                                    queryObj = yield (0, HotProcessInput_1.processInput)(method.validateQueryInput, method.parameters, queryObj, request);
                            }
                            catch (ex) {
                                let statusCode = 400;
                                if (ex.statusCode != null)
                                    statusCode = ex.statusCode;
                                logger.error(`Query validation error ${statusCode}: ${ex.message}`);
                                return ({ error: ex.message, errorCode: statusCode });
                            }
                        }
                    }
                }
            }
            if (jsonObj != null) {
                if (method.validateJSONInput != null) {
                    let skipValidation = false;
                    if (jsonObj["hotstaq"] != null) {
                        if (jsonObj["hotstaq"]["skipValidation"] != null)
                            skipValidation = jsonObj["hotstaq"]["skipValidation"];
                    }
                    if (skipValidation === false) {
                        try {
                            if (method.onValidateJSONInput != null)
                                yield method.onValidateJSONInput.call(thisObj, jsonObj);
                            else
                                jsonObj = yield (0, HotProcessInput_1.processInput)(method.validateJSONInput, method.parameters, jsonObj, request);
                        }
                        catch (ex) {
                            let statusCode = 400;
                            if (ex.statusCode != null)
                                statusCode = ex.statusCode;
                            logger.error(`JSON validation error ${statusCode}: ${ex.message}`);
                            return ({ error: ex.message, errorCode: statusCode });
                        }
                    }
                }
            }
            if (method.onServerExecute != null) {
                let hotstaq = jsonObj["hotstaq"];
                let foundUploadId = "";
                if (hotstaq != null) {
                    if (hotstaq["uploads"] != null) {
                        if (hotstaq["uploads"]["uploadId"] != null) {
                            let hotstaqUploadId = hotstaq["uploads"]["uploadId"];
                            if (server.uploads[hotstaqUploadId] != null) {
                                hotstaq["uploads"]["files"] = server.uploads[hotstaqUploadId];
                                foundUploadId = hotstaqUploadId;
                            }
                        }
                    }
                }
                try {
                    let files = null;
                    if (foundUploadId !== "") {
                        files = {};
                        files = server.uploads[foundUploadId];
                    }
                    request.authorizedValue = authorizationValue;
                    request.jsonObj = jsonObj;
                    request.queryObj = queryObj;
                    request.files = files;
                    if (req.headers.authorization != null) {
                        request.bearerToken = req.headers.authorization;
                        request.bearerToken = request.bearerToken.substring(7);
                    }
                    let result = null;
                    request.passObject = { passType: HotRouteMethod_1.PassType.Ignore, jsonObj: null };
                    if (method.onServerPreExecute != null) {
                        result = yield method.onServerPreExecute.call(thisObj, request);
                        if (logger.showHTTPEvents === true) {
                            logger.verbose((result2) => {
                                let resultStr = "";
                                if (logger.showResponses === true)
                                    resultStr = JSON.stringify(result2);
                                return (`${req.method} ${methodName}, PreExecute: ${resultStr}`);
                            }, result);
                        }
                        if (request.passObject.passType != null) {
                            if (request.passObject.passType === HotRouteMethod_1.PassType.Update)
                                request.passObject.jsonObj = result;
                            if (request.passObject.passType === HotRouteMethod_1.PassType.ReturnToClient)
                                return (request.passObject.jsonObj);
                        }
                    }
                    result = yield method.onServerExecute.call(thisObj, request);
                    if (method.onServerPostExecute != null) {
                        if (request.passObject.passType != null) {
                            if (request.passObject.passType === HotRouteMethod_1.PassType.Update)
                                request.passObject.jsonObj = result;
                            if (request.passObject.passType === HotRouteMethod_1.PassType.ReturnToClient)
                                return (request.passObject.jsonObj);
                        }
                        result = yield method.onServerPostExecute.call(thisObj, request);
                        if (logger.showHTTPEvents === true) {
                            logger.verbose((result2) => {
                                let resultStr = "";
                                if (logger.showResponses === true)
                                    resultStr = JSON.stringify(result2);
                                return (`${req.method} ${methodName}, PostExecute: ${resultStr}`);
                            }, result);
                        }
                        if (result !== undefined)
                            return (result);
                    }
                    if (logger.showHTTPEvents === true) {
                        logger.verbose((result2) => {
                            let resultStr = "";
                            if (logger.showResponses === true)
                                resultStr = `, Response: ${JSON.stringify(result2)}`;
                            return (`${req.method} ${methodName}${resultStr}`);
                        }, result);
                    }
                    if (result !== undefined)
                        return (result);
                }
                catch (ex) {
                    let statusCode = 400;
                    if (ex.statusCode != null)
                        statusCode = ex.statusCode;
                    logger.error(`HTTP Execution Error ${statusCode}: ${ex.message}`);
                    return ({ error: ex.message, errorCode: statusCode });
                }
                if (foundUploadId !== "") {
                    if (server.autoDeleteUploadOptions.afterUploadIdUse === true)
                        yield server.deleteUploads(foundUploadId);
                }
            }
        }
        else {
            logger.error(`${req.method} ${methodName}, not_authorized`);
            return (route.errors["not_authorized"]);
        }
    });
}
//# sourceMappingURL=HotHTTPServerProcessRequest.js.map