{{#if (or options.validateRequest options.validateResponse)}}
import Ajv, { ErrorObject } from 'ajv';
{{/if}}
import { stringify, StringifiableRecord } from 'query-string';
import { serialize as objectToFormData } from 'object-to-formdata';

{{#if (or options.validateRequest options.validateResponse)}}
const ajv = new Ajv({
  strict: false,
  formats: {
    int32: true,
    int64: true,
    float: true,
    double: true,
    binary: true,
    byte: true,
    password: true,
  },
});
{{/if}}

{{> errors this}}

{{> config this}}

{{models}}

const jsToUrlEncoded: (element: any, key?: string, list?: string[]) => string = function jsToUrlEncoded(element, key = '', list = []) {
  const components = list;

  if(typeof element === 'object'){
    for (let idx in element) {
      jsToUrlEncoded(element[idx], key ? `${key}[${idx}]` : idx, components);
    }
  } else {
    components.push(`${encodeURIComponent(key)}=${encodeURIComponent(element)}`);
  }

  return components.join('&');
}

export interface OperationResponse<T> {
  json: T | null;
  text: string;
  headers: Headers;
}

{{#each operations}}
  {{models}}
{{/each}}
{{#each operations}}
  {{#if (or query header params data)}}
    export interface {{capitalize name}}Request {
      {{#if query}}
      query?: {{capitalize name}}Query;
      {{/if}}
      {{#if params}}
      params?: {{capitalize name}}Params;
      {{/if}}
      {{#if data}}
        data?: FormData | {{capitalize name}}RequestBody{{capitalize mimeTypeSuffix}};
      {{/if}}
      {{#if header}}
      headers?: {{capitalize name}}Headers,
      {{/if}}
    }
  {{/if}}
  {{#if (or query header params data)}}
  export const {{name}}: (request: {{capitalize name}}Request, config?: Partial<Config>) => Promise<OperationResponse<{{capitalize name}}Response>> = async ({
      {{#if query}}
        query = {},
      {{/if}}
      {{#if params}}
        params = {},
      {{/if}}
      {{#if data}}
        data = {},
      {{/if}}
      {{#if header}}
        headers = {},
      {{/if}}
    } = {}, currentConfig = defaultConfig) => {
  {{else}}
    export const {{name}}: (config?: Partial<Config>) => Promise<OperationResponse<{{capitalize name}}Response>> = async (currentConfig = defaultConfig) => {
  {{/if}}
  const config = { ...defaultConfig, ...currentConfig };

  {{#if (or query params)}}
    let requestUrl = `${config.baseUrl}{{path}}`;
  {{else}}
    const requestUrl = `${config.baseUrl}{{path}}`;
  {{/if}}


  {{> queryString operation=this options=../options }}

  {{> parameters operation=this options=../options }}

  {{> headers operation=this options=../options }}

  {{> body operation=this options=../options }}

  {{> request operation=this options=../options }}
  }
{{/each}}

