import { Inject, Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, take } from "rxjs/operators";
import { WEB_SERVICE_CONFIG } from "app/core/provider-name-token";
import { WebServiceConfig } from "app/core/web-service-config";

export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'

@Injectable({
  providedIn: 'root'
})
export class RequestService {

  constructor(
    private http: HttpClient,
    @Inject(WEB_SERVICE_CONFIG) private webServiceConfig: WebServiceConfig
  ) {
  }

  handleError(error: HttpErrorResponse) {
    return throwError(error)
  }


  json(url: string): Observable<any> {
    return this.http.get(url);
  }

  /**
   * Sends an `HTTPRequest` and returns the response body as a JSON object.
   * @param method  The HTTP method.
   * @param url     The endpoint URL.
   * @param params The HTTP params to send with the request.
   * @returns An `Observable` of the response body as a JSON object.
   */
  public request<T>(url: string, method: HttpMethod,
                    params: object = {}
  ): Observable<Object> {
    let httpParams = new HttpParams()
    if (params) {
      Object.keys(params).forEach((key) => {
        httpParams = httpParams.append(key, params[key])
      })
    }

    switch (method) {
      case "GET": {
        return this.http.get<T>(url, { params: httpParams })
        .pipe(take(1), catchError(this.handleError))
      }
      case "POST": {
        return this.http.post<T>(url, null, { params: httpParams })
        .pipe(take(1), catchError(this.handleError))
      }
      case "PUT": {
        return this.http.put<T>(url, null, { params: httpParams })
        .pipe(take(1), catchError(this.handleError))
      }
      case "PATCH": {
        return this.http.patch<T>(url, null, { params: httpParams })
        .pipe(take(1), catchError(this.handleError))
      }
      case "DELETE": {
        return this.http.delete<T>(url, { params: httpParams })
        .pipe(take(1), catchError(this.handleError))
      }
      default: {
        break;
      }
    }
  }

  /**
   * Sends an `HTTPRequest` and returns the response body as a JSON object.
   * @param procedure  The procedure name.
   * @param params     The parameter of procedure.
   * @returns An `Observable` of the response body as a JSON object.
   */
  public sp<T>(procedure: string,
               params: object = {}
  ): Observable<Object> {
    let url = this.webServiceConfig.webServiceUrl + '/api/appdata'
    let body = { APP_DATA_PROCEDURE: procedure, ...params }
    return this.http.post<T>(url, body)
    .pipe(take(1), catchError(this.handleError))
  }

}
