/* tslint:disable */

import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { DefaultHttpOptions, HttpOptions, {{&interfaceName}} } from './';

{{#definitions.length}}
import * as models from '.{{#swaggerTag}}./..{{/swaggerTag}}/models';
{{/definitions.length}}

export const USE_DOMAIN = new InjectionToken<string>('{{&serviceName}}_USE_DOMAIN');
export const USE_HTTP_OPTIONS = new InjectionToken<HttpOptions>('{{&serviceName}}_USE_HTTP_OPTIONS');

type APIHttpOptions = HttpOptions & {
  headers: HttpHeaders;
  params: HttpParams;
  responseType?: 'arraybuffer' | 'blob' | 'text' | 'json';
};

/**
 * Created with https://github.com/flowup/api-client-generator
 */
@Injectable()
export class {{&serviceName}} implements {{&interfaceName}} {

  readonly options: APIHttpOptions;

  readonly domain: string = `{{&domain}}`;

  constructor(private readonly http: HttpClient,
              @Optional() @Inject(USE_DOMAIN) domain?: string,
              @Optional() @Inject(USE_HTTP_OPTIONS) options?: DefaultHttpOptions) {

    if (domain != null) {
      this.domain = domain;
    }

    this.options = {
      headers: new HttpHeaders(options && options.headers ? options.headers : {}),
      params: new HttpParams(options && options.params ? options.params : {}),
      ...(options && options.reportProgress ? { reportProgress: options.reportProgress } : {}),
      ...(options && options.withCredentials ? { withCredentials: options.withCredentials } : {})
    };
  }

{{#methods}}
  {{#description}}
  /**
   * {{&.}}
   */
{{/description}}  {{&methodName}}(
  {{#parameters.length}}
    args: {
      {{#parameters}}
      {{&camelCaseName}}{{^isRequired}}?{{/isRequired}}: {{&importType}}{{#isArray}}[]{{/isArray}},{{#description}}  //{{^isRequired}} (optional){{/isRequired}} {{&.}}{{/description}}
      {{/parameters}}
    },
  {{/parameters.length}}
    requestHttpOptions?: HttpOptions
  ): Observable<{{&response}}> {
    const path = `{{&path}}`;
    const options: APIHttpOptions = {
      ...this.options,
      ...requestHttpOptions,{{#requestResponseType}}
      responseType: 'blob',{{/requestResponseType}}
    };

    {{#parameters}}
      {{#isQueryParameter}}
    if ('{{&camelCaseName}}' in args) {
          {{#isArray}}
      if (args.{{&camelCaseName}} && args.{{&camelCaseName}}.length) {
        options.params = args.{{&camelCaseName}}.reduce<HttpParams>((acc, cur) => acc.append('{{&name}}', `${cur}`), options.params);
      }
          {{/isArray}}
          {{^isArray}}
      options.params = options.params.set('{{&name}}', String(args.{{&camelCaseName}}));
          {{/isArray}}
    }
      {{/isQueryParameter}}
      {{#isHeaderParameter}}
    if ('{{&camelCaseName}}' in args) {
          {{#isArray}}
      if (args.{{&camelCaseName}} && args.{{&camelCaseName}}.length) {
        options.headers = options.headers.set('{{&name}}', args.{{&camelCaseName}}.map(value => `${value}`));
      }
          {{/isArray}}
          {{^isArray}}
      options.headers = options.headers.set('{{&name}}', String(args.{{&camelCaseName}}));
          {{/isArray}}
    }
      {{/isHeaderParameter}}
    {{/parameters}}
    {{#formData.length}}
    const formData = new FormData();
    {{#formData}}
    formData.append('{{&name}}', args.{{&camelCaseName}});
    {{/formData}}

    {{/formData.length}}
    return this.sendRequest<{{&response}}>('{{methodType}}', path, options{{#parameters}}{{#isBodyParameter}}, JSON.stringify(args.{{&camelCaseName}}){{/isBodyParameter}}{{/parameters}}{{#formData.length}}, formData{{/formData.length}});
  }

{{/methods}}
  private sendRequest<T>(method: string, path: string, options: HttpOptions, body?: any): Observable<T> {
    switch (method) {
      case 'DELETE':
        return this.http.delete<T>(`${this.domain}${path}`, options);
      case 'GET':
        return this.http.get<T>(`${this.domain}${path}`, options);
      case 'HEAD':
        return this.http.head<T>(`${this.domain}${path}`, options);
      case 'OPTIONS':
        return this.http.options<T>(`${this.domain}${path}`, options);
      case 'PATCH':
        return this.http.patch<T>(`${this.domain}${path}`, body, options);
      case 'POST':
        return this.http.post<T>(`${this.domain}${path}`, body, options);
      case 'PUT':
        return this.http.put<T>(`${this.domain}${path}`, body, options);
      default:
        console.error(`Unsupported request: ${method}`);
        return throwError(`Unsupported request: ${method}`);
    }
  }
}
