/*
 * Copyright (C) 2018, 2019 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
import {HttpClient, HttpResponse} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {
  HttpClientInterface,
  HttpClientRequest,
} from '@openstapps/api/lib/http-client-interface';

/**
 * HttpClient that is based on the Angular HttpClient (@TODO: move it to provider or independent package)
 */
@Injectable()
export class StAppsWebHttpClient implements HttpClientInterface {
  /**
   *
   * @param http TODO
   */
  constructor(private readonly http: HttpClient) {}

  /**
   * Make a request
   *
   * @param requestConfig Configuration of the request
   */
  async request<TYPE_OF_BODY>(
    requestConfig: HttpClientRequest,
  ): Promise<Response<TYPE_OF_BODY>> {
    const options: {
      /**
       * TODO
       */
      [key: string]: unknown;
      /**
       * TODO
       */
      observe: 'response';
    } = {
      body: {},
      observe: 'response',
      responseType: 'json',
    };

    if (typeof requestConfig.body !== 'undefined') {
      options.body = requestConfig.body;
    }

    if (typeof requestConfig.headers !== 'undefined') {
      options.headers = requestConfig.headers;
    }

    try {
      const response: HttpResponse<TYPE_OF_BODY> = await this.http
        .request<TYPE_OF_BODY>(
          requestConfig.method || 'GET',
          requestConfig.url.toString(),
          options,
        )
        .toPromise();

      // eslint-disable-next-line prefer-object-spread
      return Object.assign(response, {
        statusCode: response.status,
        body: response.body || {},
      });
    } catch (error) {
      throw new Error(error);
    }
  }
}

/**
 * Response with generic for the type of body that is returned from the request
 */
export interface Response<TYPE_OF_BODY> extends HttpResponse<TYPE_OF_BODY> {
  /**
   * TODO
   */
  body: TYPE_OF_BODY;
  /**
   * TODO
   */
  statusCode: number;
}
