/* tslint:disable */
/* eslint-disable */
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
  import { Controller, ValidationService, FieldErrors, ValidateError, TsoaRoute, HttpStatusCodeLiteral, TsoaResponse, fetchMiddlewares } from '@namecheap/tsoa-runtime';
{{#each controllers}}
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
import { {{name}} } from '{{modulePath}}';
{{/each}}
{{#if authenticationModule}}
import { hapiAuthentication } from '{{authenticationModule}}';
// @ts-ignore - no great way to install types from subpackage
{{#if esm}}
import promiseAny from 'promise.any';
{{else}}
const promiseAny = require('promise.any');
{{/if}}
{{/if}}
{{#if iocModule}}
import { iocContainer } from '{{iocModule}}';
import { IocContainer, IocContainerFactory } from '@namecheap/tsoa-runtime';
{{/if}}
import { boomify, isBoom, Payload } from '@hapi/boom';
import { Request, RouteOptionsPreAllOptions } from '@hapi/hapi';

// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

const models: TsoaRoute.Models = {
    {{#each models}}
    "{{@key}}": {
        {{#if enums}}
        "dataType": "refEnum",
        "enums": {{{json enums}}},
        {{/if}}
        {{#if properties}}
        "dataType": "refObject",
        "properties": {
            {{#each properties}}
            "{{@key}}": {{{json this}}},
            {{/each}}
        },
        "additionalProperties": {{{json additionalProperties}}},
        {{/if}}
        {{#if type}}
        "dataType": "refAlias",
        "type": {{{json type}}},
        {{/if}}
    },
    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
    {{/each}}
};
const validationService = new ValidationService(models);

// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

export function RegisterRoutes(server: any) {
    // ###########################################################################################################
    //  NOTE: If you do not see routes for all of your controllers in this file, then you might not have informed tsoa of where to look
    //      Please look into the "controllerPathGlobs" config option described in the readme: https://github.com/lukeautry/tsoa
    // ###########################################################################################################
    {{#each controllers}}
    {{#each actions}}
        server.route({
            method: '{{method}}',
            path: '{{fullPath}}',
            options: {
                pre: [
                    {{#if security.length}}
                    {
                      method: authenticateMiddleware({{json security}})
                    },
                    {{/if}}
                    {{#if uploadFile}}
                    {
                      method: fileUploadMiddleware('{{uploadFileName}}', false)
                    },
                    {{/if}}
                    {{#if uploadFiles}}
                    {
                      method: fileUploadMiddleware('{{uploadFilesName}}', true)
                    },
                    {{/if}}
                    ...(fetchMiddlewares<RouteOptionsPreAllOptions>({{../name}})),
                    ...(fetchMiddlewares<RouteOptionsPreAllOptions>({{../name}}.prototype.{{name}})),
                ],
                {{#if uploadFile}}
                payload: {
                  output: 'stream',
                  parse: true,
                  multipart: true,
                  allow: 'multipart/form-data'
                },
                {{else if uploadFiles}}
                payload: {
                  output: 'stream',
                  parse: true,
                  multipart: true,
                  allow: 'multipart/form-data'
                },
                {{/if}}
                handler: {{#if ../../iocModule}}async {{/if}}function {{../name}}_{{name}}(request: any, h: any) {
                    const args = {
                        {{#each parameters}}
                            {{@key}}: {{{json this}}},
                        {{/each}}
                    };

                    let validatedArgs: any[] = [];
                    try {
                        validatedArgs = getValidatedArgs(args, request, h);
                    } catch (err) {
                        const error = err as any;
                        if (isBoom(error)) {
                            throw error;
                        }

                        const boomErr = boomify(error instanceof Error ? error : new Error(error.message));
                        boomErr.output.statusCode = error.status || 500;
                        boomErr.output.payload = {
                            name: error.name,
                            fields: error.fields,
                            message: error.message,
                        } as unknown as Payload;
                        throw boomErr;
                    }

                    {{#if ../../iocModule}}
                    const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer;

                    const controller: any = await container.get<{{../name}}>({{../name}});
                    if (typeof controller['setStatus'] === 'function') {
                        controller.setStatus(undefined);
                    }
                    {{else}}
                    const controller = new {{../name}}();
                    {{/if}}

                    const promise = controller.{{name}}.apply(controller, validatedArgs as any);
                    return promiseHandler(controller, promise, request, {{successStatus}}, h);
                }
            }
        });
        // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
    {{/each}}
    {{/each}}

    {{#if useSecurity}}

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

    function authenticateMiddleware(security: TsoaRoute.Security[] = []) {
        return async function runAuthenticationMiddleware(request: any, h: any) {

            // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

            // keep track of failed auth attempts so we can hand back the most
            // recent one.  This behavior was previously existing so preserving it
            // here
            const failedAttempts: any[] = [];
            const pushAndRethrow = (error: any) => {
                failedAttempts.push(error);
                throw error;
            };

            const secMethodOrPromises: Promise<any>[] = [];
            for (const secMethod of security) {
                if (Object.keys(secMethod).length > 1) {
                    const secMethodAndPromises: Promise<any>[] = [];

                    for (const name in secMethod) {
                        secMethodAndPromises.push(
                            hapiAuthentication(request, name, secMethod[name])
                                .catch(pushAndRethrow)
                        );
                    }

                    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

                    secMethodOrPromises.push(Promise.all(secMethodAndPromises)
                        .then(users => { return users[0]; }));
                } else {
                    for (const name in secMethod) {
                        secMethodOrPromises.push(
                            hapiAuthentication(request, name, secMethod[name])
                                .catch(pushAndRethrow)
                        );
                    }
                }
            }

            // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

            try {
                request['user'] = await promiseAny(secMethodOrPromises);
                return request['user'];
            }
            catch(err) {
                // Show most recent error as response
                const error = failedAttempts.pop();
                if (isBoom(error)) {
                    throw error;
                }

                const boomErr = boomify(error instanceof Error ? error : new Error(error.message));
                boomErr.output.statusCode = error.status || 401;
                boomErr.output.payload = {
                    name: error.name,
                    message: error.message,
                } as unknown as Payload;

                throw boomErr;
            }

            // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
        }
    }
    {{/if}}

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

    function isController(object: any): object is Controller {
        return 'getHeaders' in object && 'getStatus' in object && 'setStatus' in object;
    }

    {{#if useFileUploads}}
    function fileUploadMiddleware(fieldname: string, multiple: boolean = false) {
      return (request: Request, h: any) => {
        if (!request.payload[fieldname]) {
          return h.response(`${fieldname} is a required file(s).`).code(400);
        }

        const calculateFileInfo = (reqFile: any) => new Promise((resolve, reject) => {
          const originalname = reqFile.hapi.filename;
          const headers = reqFile.hapi.headers;
          const contentTransferEncoding = headers['content-transfer-encoding'];
          const encoding = contentTransferEncoding &&
            contentTransferEncoding[0] &&
            contentTransferEncoding[0].toLowerCase() || '7bit';
          const mimetype = headers['content-type'] || 'text/plain';
          const buffer = reqFile._data
          return resolve({
            fieldname,
            originalname,
            buffer,
            encoding,
            mimetype,
            filename: originalname,
            size: buffer.toString().length,
          })
        });

        if (!multiple) {
          return calculateFileInfo(request.payload[fieldname])
            .then(fileMetadata => {
              request.payload[fieldname] = fileMetadata;
              return h.continue;
            })
            .catch(err => h.response(err.toString()).code(500));
        } else {
          const promises = request.payload[fieldname].map((reqFile: any) => calculateFileInfo(reqFile));
          return Promise.all(promises)
            .then(filesMetadata => {
              request.payload[fieldname] = filesMetadata;
              return h.continue;
            })
            .catch(err => h.response(err.toString()).code(500));
        }
      };
    }
    {{/if}}

    function promiseHandler(controllerObj: any, promise: any, request: any, successStatus: any, h: any) {
        return Promise.resolve(promise)
            .then((data: any) => {
                let statusCode = successStatus;
                let headers;

                // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

                if (isController(controllerObj)) {
                    headers = controllerObj.getHeaders();
                    statusCode = controllerObj.getStatus() || statusCode;
                }
                return returnHandler(h, statusCode, data, headers);;
            })
            .catch((error: any) => {
                if (isBoom(error)) {
                    throw error;
                }

                const boomErr = boomify(error instanceof Error ? error : new Error(error.message));
                boomErr.output.statusCode = error.status || 500;
                boomErr.output.payload = {
                    name: error.name,
                    message: error.message,
                } as unknown as Payload;
                throw boomErr;
            });
    }

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

    function returnHandler(h: any, statusCode?: number, data?: any, headers: any = {}) {
        if (h.__isTsoaResponded) {
            return h.__isTsoaResponded;
        }

        let response = data !== null && data !== undefined
                    ? h.response(data).code(200)
                    : h.response("").code(204);

        Object.keys(headers).forEach((name: string) => {
            response.header(name, headers[name]);
        });

        if (statusCode) {
            response.code(statusCode);
        }

        h.__isTsoaResponded = response;

        return response;
    }

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

    function getValidatedArgs(args: any, request: any, h: any): any[] {
        const errorFields: FieldErrors = {};
        const values = Object.keys(args).map(key => {
            const name = args[key].name;
            switch (args[key].in) {
            case 'request':
                return request;
            case 'query':
                return validationService.ValidateParam(args[key], request.query[name], name, errorFields, undefined, {{{json minimalSwaggerConfig}}})
            case 'path':
                return validationService.ValidateParam(args[key], request.params[name], name, errorFields, undefined, {{{json minimalSwaggerConfig}}})
            case 'header':
                return validationService.ValidateParam(args[key], request.headers[name], name, errorFields, undefined, {{{json minimalSwaggerConfig}}});
            case 'body':
                return validationService.ValidateParam(args[key], request.payload, name, errorFields, undefined, {{{json minimalSwaggerConfig}}});
            case 'body-prop':
                return validationService.ValidateParam(args[key], request.payload[name], name, errorFields, 'body.', {{{json minimalSwaggerConfig}}});
            case 'formData':
                return validationService.ValidateParam(args[key], request.payload[name], name, errorFields, undefined, {{{json minimalSwaggerConfig}}});
            case 'res':
                return responder(h);
            }
        });
        if (Object.keys(errorFields).length > 0) {
            throw new ValidateError(errorFields, '');
        }
        return values;
    }

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

    function responder(h: any): TsoaResponse<HttpStatusCodeLiteral, unknown>  {
        return function(status, data, headers) {
           returnHandler(h, status, data, headers);
        };
    };

    // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
}

// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
