import { Cliente } from './../interface/cliente';
import { ErrorResponse } from './../interface/error-response';
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse} from  '@angular/common/http';
import { tap, catchError } from  'rxjs/operators';
import { Observable, BehaviorSubject, of} from  'rxjs';

import { Storage } from  '@ionic/storage';
import { AuthResponse } from  '../interface/auth-response';
import { UtilService } from '../../service/util.service';
import { HttpClientDataService } from '../../service/http-client-data.service';
import { Platform, Events } from '@ionic/angular';
import { environment } from '../../../environments/environment';

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

  public result;

  constructor(
    private  httpClient:  HttpClient, 
    private  storage:  Storage, 
    private  httpClientDataService: HttpClientDataService,
    private events: Events,
    private utilService: UtilService
    ) 
  { 
    this.errorRespose = { 
      error: true,
      errorMsg: ""
    };
    this.clientiSalvati = false;
    AuthService.clienti = [];
    AuthService.clienteSelezionato = {
      denominazione: null,
      id: null
    };
  }

  authSubject  =  new  BehaviorSubject(false);

  errorRespose : ErrorResponse;

  reset(value): Observable<ErrorResponse>{
    this.errorRespose.error = true;
    var param = UtilService.encodeBody({email: value.email});
    return this.httpClient.post<AuthResponse>(this.httpClientDataService.BASE_ADDRESS+'/autenticazione/resetpwd.do', param, this.httpClientDataService.httpOptions)
      .pipe(
      catchError(this.handleError),
      tap( (res:  AuthResponse ) => {

        if (!res.error) {
          this.errorRespose.error = false;
        }
        else{
          this.errorRespose.error = true;
          this.errorRespose.errorMsg = res.errorMsg;          
        }
      })
    );
  }

  static idReferente:string;
  static idCliente:string;
  static isClienteLoggato: boolean;
  static clienti:Cliente[];
  static clienteSelezionato: Cliente;
  private idClienteSelezionato;
  private tipoStruttura: string;

  loadClienti()
  {
    AuthService.clienteSelezionato = {
      denominazione: null,
      id: null
    };
    return this.storage.get("clienti").then((data)=>{
      AuthService.clienti = data;
      AuthService.clienteSelezionato = AuthService.clienti[0];
      return data;
    });
  }

  clienteSel;
  public clienteTrovato: Cliente;

  getCliente(id)
  {
    this.clienteSel = id;
    AuthService.clienti.forEach(this.getClienteSel, this);
  }

  getClienteSel(cliente, index)
  {
    if(cliente.id == this.clienteSel) this.clienteTrovato = cliente;
  }

  setCliente(id)
  {
    this.idClienteSelezionato = id;
    AuthService.clienti.forEach(this.findCliente, this);
  }

  findCliente(cliente, index)
  {
    if(cliente.id == this.idClienteSelezionato) AuthService.clienteSelezionato = cliente;
  }

  getId()
  {
    return this.getFromStorageAsync("idUser").then(state => {
      return state;
    });
  }

  getName()
  {
    return this.getFromStorageAsync("name").then(state => {
      return state;
    });
  }

  getFromStorageAsync(param){
    return this.storage.get(param).then((data)=>{
      if(param == "idUser") AuthService.idReferente = data;
      return data;
    });
  }

  changePwd(value): Observable<ErrorResponse>{
    var param = UtilService.encodeBody({
      idutente: AuthService.idReferente,
      oldpassword: value.oldpassword,
      newpassword: value.newpassword
    });
    return this.httpClient.post<AuthResponse>(this.httpClientDataService.BASE_ADDRESS+'/autenticazione/changepwd.do', param, this.httpClientDataService.httpOptions)
      .pipe(
      catchError(this.handleError),
      tap( (res:  AuthResponse ) => {

        if (!res.error) {
          this.errorRespose.error = false;
        }
        else{
          this.errorRespose.error = true;
          this.errorRespose.errorMsg = res.errorMsg;          
        }
      })
    );
  }

  clientiSalvati: boolean;

  areClientiSalvati() : boolean
  {
    return this.clientiSalvati;
  }

  registra(value) : Observable<ErrorResponse>{
    this.tipoStruttura = environment.struttura;
    var param = UtilService.encodeBody({nome: value.nome, cognome: value.cognome, email: value.email, cellulare: value.cellulare, password: value.password, tipostruttura: this.tipoStruttura});
    this.clientiSalvati = false;
    return this.httpClient.post<ErrorResponse>(this.httpClientDataService.BASE_ADDRESS+'/autenticazione/registrazione.do', param, this.httpClientDataService.httpOptions)
    .pipe(
      catchError(this.handleError),
      tap( (res:  AuthResponse ) => {
        if (!res.error) {
          this.authSubject.next(true);
          AuthService.isClienteLoggato = res.cliente;
          if(!res.cliente) AuthService.idReferente = res.toString();
          else AuthService.idCliente = res.id.toString();
          this.storage.set("idUser",res.id).then((successData)=>{
            console.log("Data Stored");
            console.log(successData);
          });
          this.storage.set("name",res.nome);
          this.storage.set("isCliente", res.cliente);
          this.storage.set("clienti", res.clienti).then((successData)=>{
            this.clientiSalvati = true;
            this.events.publish('functionCall:startup', null);
          });
          this.storage.set("logged",true);
          this.errorRespose.error = false;
        }
        else{
          this.errorRespose.error = true;
          this.errorRespose.errorMsg = res.errorMsg;          
        }
      })
    );
  }

  login(value) : Observable<ErrorResponse>{
    this.tipoStruttura = environment.struttura;
    var param = UtilService.encodeBody({utente: value.username, password: value.password, tipostruttura: this.tipoStruttura});
    this.clientiSalvati = false;
    return this.httpClient.post<ErrorResponse>(this.httpClientDataService.BASE_ADDRESS+'/autenticazione/login.do', param, this.httpClientDataService.httpOptions)
    .pipe(
      catchError(this.handleError),
      tap( (res:  AuthResponse ) => {
        if (!res.error) {
          this.authSubject.next(true);
          AuthService.isClienteLoggato = res.cliente;
          if(!res.cliente) AuthService.idReferente = res.id.toString();
          else AuthService.idCliente = res.id.toString();
            this.storage.set("idUser",res.id).then((successData)=>{
              console.log("Data Stored");
              console.log(successData);
            });
            this.storage.set("name",res.nome);
            this.storage.set("isCliente", res.cliente);
            this.storage.set("clienti", res.clienti).then((successData)=>{
              this.clientiSalvati = true;
              this.events.publish('functionCall:startup', null);
            });
            this.storage.set("logged",true);
          this.errorRespose.error = false;
        }
        else{
          this.errorRespose.error = true;
          this.errorRespose.errorMsg = res.errorMsg;          
        }
      })
    );
  }
  
  

  handleError(error: HttpErrorResponse) {
    this.errorRespose = { 
      error: true,
      errorMsg: ""
    };
    if (error.error instanceof ErrorEvent) {
      this.errorRespose.errorMsg = error.error.message;
    } else {
      this.errorRespose.errorMsg = error.error;
    }
    return of(this.errorRespose);
  };

  async logout() {
    this.storage.set("logged",false).then((successData)=>{
      console.log("Data Stored");
      console.log(successData);
    })
    this.authSubject.next(false);
    this.utilService.sendRegistration(AuthService.idReferente, '', '', !AuthService.isClienteLoggato);
  }

  isLoggedIn(){
    return this.storage.get("logged").then((data)=>{
      return data;
    });
  }

  async syncIsLoggedIn()
  {
    return await this.storage.get("logged");
  }
}
