import { Injectable } from '@angular/core';
import {
  HttpClient,
  HttpHeaders,
  HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, retry, tap, timeout } from 'rxjs/operators';
import { CommonService } from '../common/common.service';
// import { Response } from "../models/response";
import { Response } from 'src/app/hmg-common/services/models/response';
import { Events } from "@ionic/angular";
import { GetLoginInfoResponse } from "src/app/hmg-common/services/authentication/models/get-login-info.response";
import { GetLoginInfoRequest } from "src/app/hmg-common/services/authentication/models/get-login-info.request";
import { TranslatorService } from "../translator/translator.service";

@Injectable({
  providedIn: 'root'
})
export class ConnectorService {
  /*
  connection configuration settings
  */
  static httpOptions = {
    headers: new HttpHeaders({ 'Content-Type': 'application/json' })
  };
  public static retryTimes = 0;
  public static timeOut = 120 * 1000;

  // public static host = 'https://uat.hmgwebservices.com/';
  public static host = 'https://hmgwebservices.com/';

  constructor(public httpClient: HttpClient,
    public cs: CommonService,
    private events: Events,
    public ts: TranslatorService) { }

  public post(
    service: string,
    data: any,
    onError: any,
    errorLabel?: string,
    fromSMS = false
  ): Observable<any> {
    this.cs.startLoading();
    return this.httpClient
      .post<any>(
        ConnectorService.host + service,
        data,
        ConnectorService.httpOptions
      )
      .pipe(
        timeout(ConnectorService.timeOut),
        retry(ConnectorService.retryTimes),
        tap(
          res => this.handleResponse(res, onError, errorLabel, false, fromSMS),
          error => this.handleError(error, onError, errorLabel)
        )
      );
  }

  public postItg(
    service: string,
    data: any,
    onError: any,
    errorLabel?: string
  ): Observable<any> {
    this.cs.startLoading();
    return this.httpClient
      .post<any>(
        ConnectorService.host + service,
        data,
        ConnectorService.httpOptions
      )
      .pipe(
        timeout(ConnectorService.timeOut),
        retry(ConnectorService.retryTimes),
        tap(
          res => this.handleResponseItg(res, onError, errorLabel),
          error => this.handleError(error, onError, errorLabel)
        )
      );
  }



  // public postNoLoad(service: string, data: any, onError: any): Observable<any> {
  //   return this.httpClient
  //     .post<any>(
  //       ConnectorService.host + service,
  //       data,
  //       ConnectorService.httpOptions
  //     )
  //     .pipe(
  //       retry(ConnectorService.retryTimes),
  //       tap(() => {}, () => {})
  //     );
  // }

  public postNoLoad(service: string, data: any, onError: any, errorLabel?: string): Observable<any> {
    return this.httpClient
      .post<any>(
        ConnectorService.host + service,
        data,
        ConnectorService.httpOptions)
      .pipe(
        timeout(ConnectorService.timeOut),
        retry(ConnectorService.retryTimes),
        tap((res) => {
          this.handleResponse(res, onError, errorLabel, true);
        }, (error) => {
          this.handleError(error, onError, errorLabel, true);
        }));
  }

  // absolute url connection
  public postToken(
    service: string,
    data: any,
    onError: any,
    errorLabel?: string
  ): Observable<any> {
    this.cs.startLoading();
    return this.httpClient
      .post<any>(service, data, ConnectorService.httpOptions)
      .pipe(
        timeout(ConnectorService.timeOut),
        retry(ConnectorService.retryTimes),
        tap(
          res => this.handleResponse(res, onError, errorLabel),
          error => this.handleError(error, onError, errorLabel)
        )
      );
  }

  public get(
    service: string,
    data: any,
    onError: any,
    errorLabel?: string
  ): Observable<any> {
    this.cs.startLoading();
    return this.httpClient.get(service, ConnectorService.httpOptions).pipe(
      timeout(ConnectorService.timeOut),
      retry(ConnectorService.retryTimes),
      tap(
        res => this.handleResponse(res, onError, errorLabel),
        error => this.handleError(error, onError, errorLabel)
      )
    );
  }
  /*
    load local json data and convert it to corresponding model
    resourceURL such as 'assets/config.json'
    */
  public getLocalResrouce(resourceURL: string): Observable<any> {
    return this.httpClient.get(resourceURL);
  }

  /*
    public validResponse(result: Response): boolean {
        // error type == 2 means you have error
        if (result.MessageStatus === 1) {
            return true;
        } else if (result.MessageStatus === 2) {
            return this.cs.hasData(result['SameClinicApptList']);
        }
        return false;
    }
    */

  public handleError(error: any, onError: any, errorLabel: string, isPostNoLoad = false) {
    // if (!isPostNoLoad) {
    //   this.cs.stopLoading();
    // }
    this.cs.stopLoading();
    if (error instanceof TimeoutError) {
      this.cs.showConnectionTimeout(onError, errorLabel);
    } else {
      this.cs.showConnectionErrorDialog(onError, errorLabel);
    }
  }

  public getLoginInfo(
    request: any,
    onError: any,
    errorLabel: string
  ): Observable<GetLoginInfoResponse> {
    //this.setPublicFields(request);
    return this.post(
      'Services/ERP.svc/REST/Mohemm_GetMobileLoginInfo_NEW',
      request,
      onError,
      errorLabel
    );
  }

  public getLastLoginInfo() {
    let deviceToken = localStorage.getItem('deviceToken');

    const requestGetLoginInfo = {
      DeviceType: this.cs.getDeviceType(),
      DeviceToken: deviceToken
    };

    this.getLoginInfo(requestGetLoginInfo, () => { }, this.ts.trPK('general', 'ok')).subscribe(res => {
      if (this.cs.validResponse(res)) {
        if (res.Mohemm_GetMobileLoginInfoList.length > 0) {
          this.cs.sharedService.setSharedData(res.Mohemm_GetMobileLoginInfoList[0], 'imei-user-data');
          const user = true;
          this.events.publish('user', user);
          this.cs.openLogin();
        } else {
          const user = false;
          this.events.publish('user', user);
          this.cs.openLogin();
        }
      } else { }
    });
  }

  public handleResponse(result: Response, onError: any, errorLabel: string, isPostNoLoad = false, fromSMS = false) {
    console.log('fromSMSValue ' + fromSMS)
    if (!isPostNoLoad) {
      this.cs.stopLoading();
    }
    if (!this.cs.validResponse(result)) {
      if (result.IsAuthenticated === false) {
        this.cs.stopLoading();
        if (!fromSMS) {
          this.cs.presentAcceptDialog(result.ErrorEndUserMessage, () => {
            this.cs.sharedService.clearAll();
            this.getLastLoginInfo();
          });
        }
        return false;
      } else if (result.ErrorType === 2 || result.ErrorType === 4) {
        this.cs.stopLoading(); 
      } else {
        this.cs.stopLoading();
        if (!fromSMS) {
          this.cs.showErrorMessageDialog(
            onError,
            errorLabel,
            result.ErrorEndUserMessage
          );
        } else {
          console.log('its an error from sms')
        }

        //add flag if user not auth

      }
    }
  }

  public handleResponseItg(result: Response, onError: any, errorLabel: string, isPostNoLoad = false) {
    console.log("handleResponseItg");
    if (!isPostNoLoad) {
      this.cs.stopLoading();
    }
    if (!this.cs.validResponse(result)) {
      if (result.IsAuthenticated === false) {
        this.cs.stopLoading();
        this.cs.presentAcceptDialog(result.ErrorEndUserMessage, () => {
          console.log("presentAcceptDialog");
          this.cs.sharedService.clearAll();
          // this.cs.openLogin();
          this.getLastLoginInfo();
        });
        return false;
      } else if (result.ErrorType === 2 || result.ErrorType === 4) {
        console.log("ErrorType if");

        // console.log("error expired");
        this.cs.stopLoading();
      } else {
        console.log("ErrorType else");

        this.cs.stopLoading();
        // this.cs.showErrorMessageDialog(
        //   onError,
        //   errorLabel,
        //   result.Message
        // );
        //add flag if user not auth

      }
    }
  }
  public getURLText(
    url: string,
    onError: any,
    errorLabel?: string
  ): Observable<any> {
    this.cs.startLoading();
    return this.httpClient.get(url).pipe(
      timeout(ConnectorService.timeOut),
      retry(ConnectorService.retryTimes),
      tap(
        res => {
          this.cs.stopLoading();
          if (!res) {
            this.cs.showConnectionErrorDialog(onError, errorLabel);
          }
        },
        error => this.handleError(error, onError, errorLabel)
      )
    );
  }
}
