// ===============================================
// This file is autogenerated - Please do not edit it
// ===============================================

//see for available variables: https://github.com/swagger-api/swagger-codegen/blob/90e7bb73a9d0e71092e2d1903fbf8262e9ce2140/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java
{{>licenseInfo}}
/* eslint-disable */

import request = require('request');
import http = require('http');
{{^supportsES6}}
//import Promise = require('bluebird');
{{/supportsES6}}

{{> ../common}}

const defaultBasePath = BASE_PATH;

const appInfo = {
 title: "{{appName}}",
 version: "{{appVersion}}",
}

export function jsonReviver(key:any, value:any) {
    if (typeof value === 'string') {
        //something like 2018-04-26T17:16:07.07
        if (value.startsWith("20") && /^\d{4}-\d{2}-\d{2}/.test(value)) {
            const d= new Date(value); 
            return d;
        }
    }
    return value;
}

function pad(n: number) {
  return n < 10 ? "0" + n : n;
}

export function toISOString(d: Date) {
  return (
    d.getUTCFullYear() + "-" +
    pad(d.getUTCMonth() + 1) + "-" +
    pad(d.getUTCDate()) + "T" +
    pad(d.getUTCHours()) + ":" +
    pad(d.getUTCMinutes()) + ":" +
    pad(d.getUTCSeconds()) + "Z"
  );
}

function formatParam(p: unknown) {
  if (Object.prototype.toString.call(p) === "[object Date]") {
    return toISOString(p as Date);
  }
  return p;
}

export class ApiExceptionError extends Error {
    name = "ApiExceptionError";
    response: request.Response;
    body: any;
    serverException: ExceptionViewModel | undefined;
    constructor(response: request.Response, body: any) {
        super();
        this.response = response;
        this.body = body;
        const ex = body as ExceptionViewModel 
        if (ex && typeof ex.Code !== "undefined") {
            //for less verbose error message when printing if it is standard API ExceptionViewModel
            this.message =
                `Serverside ApiException in \`${response.request.method} ${response.request.path}\` (\`body\`, \`response\` omitted for brievity): ` +
                    ex.ErrorDetail || ex.ExceptionMessage || "impossible error!!!";
            this.serverException = ex;
            Object.defineProperty(this, "body", {
                enumerable: false,
            });
            Object.defineProperty(this, "response", {
                enumerable: false,
            });
        }
    }
    public static of(error: {
        response: request.Response;
        body: any;
    }): ApiExceptionError {
        return new ApiExceptionError(error.response, error.body);
    }
}

/* tslint:disable:no-unused-variable */

{{#models}}
{{#model}}
{{#description}}
/**
* {{{description}}}
*/
{{/description}}

{{#isEnum}}
// is an enum
export enum {{classname}}{
    {{#vendorExtensions.x-enum-pairs}} {{Name}} = "{{Name}}", {{/vendorExtensions.x-enum-pairs}}
}
{{/isEnum}}
{{^isEnum}}
// not an enum
{{#vendorExtensions.x-inheritsName}} 
export {{#vendorExtensions.x-inputModel}} class {{/vendorExtensions.x-inputModel}} {{^vendorExtensions.x-inputModel}} interface {{/vendorExtensions.x-inputModel}} {{classname}} extends {{{vendorExtensions.x-inheritsName}}} 
{{/vendorExtensions.x-inheritsName}} 
{{^vendorExtensions.x-inheritsName}} 
export {{#vendorExtensions.x-inputModel}} class {{/vendorExtensions.x-inputModel}} {{^vendorExtensions.x-inputModel}} interface {{/vendorExtensions.x-inputModel}} {{classname}}
{{/vendorExtensions.x-inheritsName}} 
{
{{> ../validator}}
{{#vars}}
{{#description}}
    /**
    * {{{description}}}
    */
{{/description}}
{{> ../property}}
{{/vars}}
}
{{/isEnum}}
{{/model}}
{{/models}}

export interface Authentication {
    /**
    * Apply authentication settings to header and query params.
    */
    applyToRequest(requestOptions: request.Options): void;
}

export class HttpBasicAuth implements Authentication {
    public username: string | undefined;
    public password: string | undefined;
    applyToRequest(requestOptions: request.Options): void {
        requestOptions.auth = {
            username: this.username, password: this.password
        }
    }
}

export class ApiKeyAuth implements Authentication {
    public apiKey: string | undefined;

    constructor(private location: string, private paramName: string) {
    }

    applyToRequest(requestOptions: request.Options): void {
        if (this.location == "query") {
            (<any>requestOptions.qs)[this.paramName] = this.apiKey;
        } else if (this.location == "header" && requestOptions && requestOptions.headers) {
            requestOptions.headers[this.paramName] = this.apiKey;
        }
    }
}

export class OAuth implements Authentication {
    public accessToken: string | undefined;

    applyToRequest(requestOptions: request.Options): void {
        if (requestOptions && requestOptions.headers && this.accessToken) {
            requestOptions.headers["Authorization"] = "Bearer " + this.accessToken;
        }
    }
}

export class VoidAuth implements Authentication {
    public username: string | undefined;
    public password: string | undefined;
    applyToRequest(_: request.Options): void {
        // Do nothing
    }
}

{{#apiInfo}}
{{#apis}}
{{#operations}}
{{#description}}
/**
* {{&description}}
*/
{{/description}}
export enum {{classname}}ApiKeys {
{{#authMethods}}
{{#isApiKey}}
    {{name}},
{{/isApiKey}}
{{/authMethods}}
}

export class {{classname}} {
    protected basePath = defaultBasePath;
    protected appInfo = appInfo;
    protected defaultHeaders : any = {};
    protected _useQuerystring : boolean = false;

    protected authentications:{[k:string]:any} = {
        'default': <Authentication>new VoidAuth(),
{{#authMethods}}
{{#isBasic}}
        '{{name}}': new HttpBasicAuth(),
{{/isBasic}}
{{#isApiKey}}
        '{{name}}': new ApiKeyAuth({{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{^isKeyInHeader}}'query'{{/isKeyInHeader}}, '{{keyParamName}}'),
{{/isApiKey}}
{{#isOAuth}}
        '{{name}}': new OAuth(),
{{/isOAuth}}
{{/authMethods}}
    }

    constructor(basePath?: string);
{{#authMethods}}
{{#isBasic}}
    constructor(username: string, password: string, basePath?: string);
{{/isBasic}}
{{/authMethods}}
    constructor(basePathOrUsername: string, password?: string, basePath?: string) {
        if (password) {
{{#authMethods}}
{{#isBasic}}
            this.username = basePathOrUsername;
            this.password = password
{{/isBasic}}
{{/authMethods}}
            if (basePath) {
                this.basePath = basePath;
            }
        } else {
            if (basePathOrUsername) {
                this.basePath = basePathOrUsername
            }
        }
    }

    set useQuerystring(value: boolean) {
        this._useQuerystring = value;
    }

    public setApiKey(key: {{classname}}ApiKeys, value: string) {
        this.authentications[{{classname}}ApiKeys[key]].apiKey = value;
    }
{{#authMethods}}
{{#isBasic}}
    set username(username: string) {
        this.authentications.{{name}}.username = username;
    }

    set password(password: string) {
        this.authentications.{{name}}.password = password;
    }
{{/isBasic}}
{{#isOAuth}}

    set accessToken(token: string) {
        this.authentications.{{name}}.accessToken = token;
    }
{{/isOAuth}}
{{/authMethods}}
{{#operation}}
    /**
     * {{summary}}
     * {{notes}}
     {{#allParams}}* @param {{paramName}} {{description}}
     {{/allParams}}*/
    public {{nickname}} ({{#allParams}}{{paramName}}{{^required}}?{{/required}}:  
{{#vendorExtensions.x-enumTypeName}}
{{vendorExtensions.x-enumTypeName}} {{^required}} | null {{/required}}
{{/vendorExtensions.x-enumTypeName}}
{{^vendorExtensions.x-enumTypeName}}
{{{dataType}}} {{^required}} | null {{/required}}
{{/vendorExtensions.x-enumTypeName}}
{{#hasMore}}, {{/hasMore}}{{/allParams}}) : Promise<{ response: http.{{#supportsES6}}IncomingMessage{{/supportsES6}}{{^supportsES6}}ClientResponse{{/supportsES6}}; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }> { //mark api method name
        const localVarPath = this.basePath + '{{path}}'{{#pathParams}}
            .replace('{' + '{{baseName}}' + '}', String({{paramName}})){{/pathParams}};
        let queryParameters: any = {};
        let headerParams: any = (<any>Object).assign({}, this.defaultHeaders);
        let formParams: any = {};

{{#allParams}}{{#required}}
        // verify required parameter '{{paramName}}' is not null or undefined
        if ({{paramName}} === null || {{paramName}} === undefined) {
            throw new Error('Required parameter {{paramName}} was null or undefined when calling {{nickname}}.');
        }
{{/required}}{{/allParams}}
{{#queryParams}}
// {{vendorExtensions}}
        if ({{paramName}} !== undefined) {
            if(["longitude", "latitude"].includes('{{paramName}}')){
                headerParams['X-FHT-' + '{{baseName}}'.toUpperCase()] = "" + {{paramName}};
            }
            else {
                queryParameters['{{baseName}}'] = {{paramName}};
            }
        }

{{/queryParams}}
{{#headerParams}}
        headerParams['{{baseName}}'] = {{paramName}};

{{/headerParams}}
        let useFormData = false;

{{#formParams}}
        if ({{paramName}} !== undefined) {
            formParams['{{baseName}}'] = {{paramName}};
        }
{{#isFile}}
        useFormData = true;
{{/isFile}}

{{/formParams}}
        let requestOptions: request.Options = {
            method: '{{httpMethod}}',
            qs: queryParameters,
            headers: headerParams,
            uri: localVarPath,
            useQuerystring: this._useQuerystring,
{{^isResponseFile}}
            json: true,
            jsonReviver, 
{{/isResponseFile}}
{{#isResponseFile}}
            encoding: null,
{{/isResponseFile}}
{{#bodyParam}}
            body: {{paramName}},
{{/bodyParam}}
        };

{{#authMethods}}
        this.authentications.{{name}}.applyToRequest(requestOptions);

{{/authMethods}}
        this.authentications.default.applyToRequest(requestOptions);

        if (Object.keys(formParams).length) {
            if (useFormData) {
                (<any>requestOptions).formData = formParams;
            } else {
                requestOptions.form = formParams;
            }
        }
        return new Promise<{ response: http.{{#supportsES6}}IncomingMessage{{/supportsES6}}{{^supportsES6}}ClientResponse{{/supportsES6}}; {{#returnType}}body: {{{returnType}}}; {{/returnType}}{{^returnType}}body?: any; {{/returnType}} }>((resolve, reject) => {
            request(requestOptions, (error, response, body) => {
                if (error) {
                    reject(error);
                } else {
                    if (response.statusCode >= 200 && response.statusCode <= 299) {
                        resolve({ response: response, body: body });
                    } else {
                        reject(ApiExceptionError.of({ response: response, body: body }));
                    }
                }
            });
        });
    }
{{/operation}}
}
{{/operations}}
{{/apis}}
{{/apiInfo}}
