{{>licenseInfo}}

/* eslint-disable */

require('isomorphic-fetch');

{{> ../common}}

const isomorphicFetch = fetch;

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

function json(text:string){
    return JSON.parse(text, jsonReviver);
}

interface Dictionary<T> { [index: string]: T; }
export interface FetchAPI { (url: string, init?: any): Promise<any>; }

const url = require('url');

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 const DEFAULT_HEADERS: HeadersInit = {};

export class BaseAPI {
	public static beforeRequest?: (fetchArgs: FetchArgs) => void;
	public static afterResponse?: (url: string, response: any) => void;
	constructor(protected fetch: FetchAPI = isomorphicFetch, protected basePath: string = BASE_PATH) {
	}
	protected async callApi(fetchArgs: FetchArgs) {
		const f = this.fetch;
		BaseAPI.beforeRequest?.(fetchArgs);
		const response = await f(this.basePath + fetchArgs.url, fetchArgs.options);
		BaseAPI.afterResponse?.(this.basePath + fetchArgs.url, response);
		if (response.status >= 200 && response.status < 300) {
			return json((await response.text()) || 'null');
		}
		else {
			const json = await response.json();
			throw json;
		}
	}
}

export interface FetchArgs {
    url: string;
    options: any;
}

{{#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}} 
// x-inputModel: {{vendorExtensions.x-inputModel}} 
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}}

{{#hasEnums}}
{{/hasEnums}}
{{/model}}
{{/models}}

{{#apiInfo}}
{{#apis}}
{{#operations}}

/**
 * {{classname}} - object-oriented interface{{#description}}
 * {{&description}}{{/description}}
 */
export class {{classname}} extends BaseAPI {
{{#operation}}
    /** {{#summary}}
     * {{summary}}{{/summary}}{{#notes}}
     * {{notes}}{{/notes}}{{#allParams}}
     * @param {{paramName}} {{description}}{{/allParams}}
     */
    {{nickname}}({{#hasParams}}params: { 
{{#allParams}} 
"{{paramName}}"{{^required}}?{{/required}}: 
//mark first
{{#vendorExtensions.x-enumTypeName}}
{{vendorExtensions.x-enumTypeName}}{{^required}} | null{{/required}}
{{/vendorExtensions.x-enumTypeName}}
{{^vendorExtensions.x-enumTypeName}}
{{{dataType}}}{{^required}} | null{{/required}}
{{/vendorExtensions.x-enumTypeName}}
;{{/allParams}} }, {{/hasParams}}options?: RequestInit): Promise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}>  {

    {{#allParams}}
{{#required}}
        // verify required parameter "{{paramName}}" is set
        //if (!("{{paramName}}" in params)) {
        //    throw new Error("{{paramName}} required");
        //}
{{/required}}
{{/allParams}}
        const baseUrl = `{{path}}`{{#pathParams}}.replace(`{${"{{baseName}}"}}`, `${ params["{{paramName}}"] }`){{/pathParams}};
        let urlObj = url.parse(baseUrl, true);
{{#hasQueryParams}}
        urlObj.query = Object.assign({}, urlObj.query, {
            {{#queryParams}}
            "{{baseName}}": formatParam(params["{{paramName}}"]),
            {{/queryParams}}
        });
{{/hasQueryParams}}
        let fetchOptions: RequestInit = Object.assign({ method: "{{httpMethod}}" }, options);

        let headers: Dictionary<string> = {};
{{#hasFormParams}}
        headers = { "Content-Type": "application/x-www-form-urlencoded" };
        fetchOptions.body = querystring.stringify({
        {{#formParams}}
            "{{baseName}}": params["{{paramName}}"],
        {{/formParams}}
        });
{{/hasFormParams}}
{{#hasBodyParam}}
        headers = { "Content-Type": "application/json" };{{#bodyParam}}
        if (params["{{paramName}}"]) {
            fetchOptions.body = JSON.stringify(params["{{paramName}}"] || {});
        }{{/bodyParam}}
{{/hasBodyParam}}
{{#hasHeaderParams}}
        const extraHeaders = {
            {{#headerParams}}"{{baseName}}": params["{{paramName}}"],{{/headerParams}}
        };
        fetchOptions.headers = {...DEFAULT_HEADERS, ...headers, ...extraHeaders, ...fetchOptions.headers};
{{/hasHeaderParams}}
{{^hasHeaderParams}}
        fetchOptions.headers = {...DEFAULT_HEADERS, ...headers, ...fetchOptions.headers};
{{/hasHeaderParams}}
        return this.callApi({
            url: url.format(urlObj),
            options: fetchOptions,
        });
    }
{{/operation}}
};
{{/operations}}
{{/apis}}
{{/apiInfo}}
