import { Pair } from './../interface/pair';
import { Injectable } from '@angular/core';
import { LoadingController, AlertController, Platform } from '@ionic/angular';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { File, FileEntry} from '@ionic-native/file/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { Router } from  "@angular/router";
import { SocialSharing } from '@ionic-native/social-sharing/ngx';
import { TranslateService } from '@ngx-translate/core';
import { BehaviorSubject, Observable, of} from  'rxjs';
import { Struttura } from '../interface/struttura';
import { ParereResponse } from '../interface/parere-response';
import { catchError, tap } from 'rxjs/operators';
import { HttpClientDataService } from './http-client-data.service';
//import { PushObject, PushOptions, Push } from '@ionic-native/push/ngx';
import { ActionPerformed, PushNotificationSchema, PushNotifications, Token } from '@capacitor/push-notifications';
import { ErrorResponse } from '../auth/interface/error-response';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { AndroidPermissions } from '@ionic-native/android-permissions/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { NotificheService } from './notifiche.service';
import { environment } from '../../environments/environment';
import { AuthService } from '../auth/service/auth.service';
import { EventsService } from './events.service';
import { Storage } from '@ionic/storage-angular';

const delay = ms => new Promise(res => setTimeout(res, ms));

const wait = async () => {
  await delay(3000);
  console.log("Waited 3s");
}

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

  constructor(
    private loadingCtrl: LoadingController, 
    private alertController: AlertController,
    private  httpClient: HttpClient,
    private file: File,
    private fileOpener: FileOpener,
    private  router:  Router,
    public platform: Platform,
    private socialSharing: SocialSharing,
    private  storage:  Storage, 
    public translate: TranslateService,
    private  httpClientDataService: HttpClientDataService,
    //public push: Push,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private androidPermissions: AndroidPermissions,
    private notificheService: NotificheService
    ) {
    this.loaders = new Array();
    this.loader = this.loadingCtrl.create({
      message: "Please wait...",
    });
    this.loaders.push(this.loader);
    this.languageSelected = "";
    this.errorRespose = { 
      error: true,
      errorMsg: ""
    };
  }

  async logout() {
    const alert = await this.alertController.create({
      header: 'Conferma',
      message: 'Vuoi davvero uscire?',
      buttons: [
        {
          text: 'No',
          role: 'cancel',
          handler: () => {
          }
        },
        {
          text: 'Si',
          handler: () => {
            this.logoutUser();
            this.router.navigateByUrl('login');
          }
        }
      ]
    });
    alert.present();
  }

  authSubject  =  new  BehaviorSubject(false);

  async logoutUser() {
    this.storage.clear();
    this.storage.set("logged",false).then((successData)=>{
      console.log("Data Stored");
      console.log(successData);
    })
    this.authSubject.next(false);
    this.sendRegistration(AuthService.idReferente, '', '', !AuthService.isClienteLoggato).subscribe((res: ParereResponse)=>{});
  }

  async presentAlert(headerPar, subtitlePar, messagePar, buttonsPar) {
  
    const alert = await this.alertController.create({
      header: headerPar,
      subHeader: subtitlePar,
      message: messagePar,
      buttons: buttonsPar
    });
    return alert.present();
  }

  loader;
  loaders: Array<any>;
  private languageSelected:string;
  private static strutturaSel:Struttura;
  private static strutturaName:string;
  public static strutture: Struttura[];
  public static titoloPagina:string = "";
  public static newpage;
  public static strutturaSegreteria:Struttura;
  public static pushRegistrationId:string;
  public static redirectToNotifiche:boolean = false;
  public startup :boolean = true;

  static setStruttura(id:number)
  {
    if(this.strutture.length > 0)
    { 
      this.strutture.forEach(function (value) {
        if(value.id == id) this.utilService.setStrutturaSel(value);
        this.strutturaSel = this.utilService.getStrutturaSel();
      });
    }
  }

  getStruttura(id:number): Promise<any>
  {
    let promiseChain: Promise<any> = Promise.resolve();
    if(UtilService.strutture == null) return promiseChain;
    if(UtilService.strutture.length > 0)
    { 
      UtilService.strutture.forEach(value => {
        if(value.id == id) promiseChain = promiseChain.then(
          () => value
        )
      });
      return promiseChain;
    }
  }

  getStrutturaName()
  {
    return UtilService.strutturaName;
  }

  setStrutturaName(s: string)
  {
    UtilService.strutturaName = s;
  }

  getStrutturaSel()
  {
    return UtilService.strutturaSel;
  }

  setStrutturaSel(s: Struttura)
  {
    UtilService.strutturaSel = s;
  }

  loadLingua()
  {
    this.storage.get("lingua").then((data)=>{
      if(data != null)
      {
        this.languageSelected = data;
        this.translate.setDefaultLang(data);
        this.translate.use(data);
      }
    });
  }

  setLingua(lingua: string)
  {
    this.languageSelected = lingua;
    this.storage.set("lingua",lingua).then((successData)=>{
      console.log("Salvata lingua: "+lingua);
    });
  }

  getLingua():string
  {
    return this.languageSelected;
  }

  async showLoading() {
    if(this.platform.is("ios")) return null;
    this.loader = await this.loadingCtrl.create({
      message: "Please wait...",
    });
    this.loaders.push(this.loader);
    return await this.loader.present();
  }

  closeLoading() {
    if(this.platform.is("ios")) return null;
    if(this.loaders.length > 0)
    {
      this.loader = this.loaders.pop();
      this.loader.dismiss();
    }
    else{
      setTimeout(() => {
        this.secondClose()
      }, 2000)
    }
  }

  secondClose()
  {
    if(this.loaders.length > 0)
    {
      this.loader = this.loaders.pop();
      this.loader.dismiss();
    }
  }

  getDateString(date: Date) :string
  {
    return date.getDay() + "-" + date.getMonth() + "-" + date.getFullYear();
  }

  getAndroidDateString(date: Date) :string
  {
    return date.getDate() + "-" + (date.getMonth()+1) + "-" + date.getUTCFullYear();
  }

  static encodeBody(params) {
    var urlEncodedDataPairs = [];
    var key;
    for(key in params) {
      urlEncodedDataPairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]));
    }
    return urlEncodedDataPairs.join('&').replace(/%20/g, '+');
  }

  dateFormatConvert(date:string) :string{
    if(this.platform.is("desktop"))
    {
      var array = date.split('-');
      return array[2]+"-"+array[1]+"-"+array[0];
    }
    return date;
  }

  getLanguageList() : Array<Pair>
  {
    var langs = new Array<Pair>();
    let lang : Pair = {
      'key' :'it',
      'value': 'italiano',
      'type': ''
    }
    langs.push(lang);
    return langs;
  }

  static getMIMEtype(extn){
    let ext=extn.toLowerCase();
    let MIMETypes={
      'txt' :'text/plain',
      'docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'doc' : 'application/msword',
      'pdf' : 'application/pdf',
      'jpg' : 'image/jpeg',
      'bmp' : 'image/bmp',
      'png' : 'image/png',
      'gif' : 'image/gif',
      'xls' : 'application/vnd.ms-excel',
      'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'rtf' : 'application/rtf',
      'ppt' : 'application/vnd.ms-powerpoint',
      'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
    }
    return MIMETypes[ext];
  }

  static wait()
  {
    wait();
  }

  fileScaricati: Array<string>;
  datiScaricati: Array<Blob>;
  files: Array<Pair>;
  count: number;
  total: number;

  shareDocumenti(fileSel : Array<Pair>)
  {
    this.count = 0;
    this.fileScaricati = new Array();
    this.datiScaricati = new Array();
    this.files = fileSel;
    this.showLoading();
    /*var i = 0;
    while(i < fileSel.length)
    {
      var fileInfo : Pair = fileSel.pop();
      var path = this.file.externalDataDirectory;
      var
      nomeFile = nomeFile.replace(/\//g, "-");
      this.download(fileInfo.value)
        .subscribe(
        (data) => { // Success
          this.file.writeFile(path, fileInfo.key, data, { replace: true }).then((fileEntry: FileEntry) => {
            this.fileScaricati.push(fileEntry.toURL());
          },
          (error) =>{
            console.log(error);
          }
        );
      });
      i++;
    }*/
    this.total = fileSel.length;
    fileSel.forEach(this.saveFile, this);
    if(this.count == this.total) this.share();
    else setTimeout(() => {
      this.share()
    }, 1000);
  }

  share(){
    if(this.count != this.total) setTimeout(() => {
      this.share()
    }, 1000);
    else{
      this.closeLoading();
        this.socialSharing.share(null, null, this.fileScaricati, null).then(() => {
          console.log("File condiviso con successo!");
        }).catch((e) => {
          this.presentAlert("Avviso", "", 'Errore durante la condivisione dei file', ["OK"]);
          console.log('Errore durante la condivisione dei file:' + e);
        });
    }
  }

  async saveFile(fileInfo: Pair, index)
  {
    var path = "";
    if(this.platform.is("ios")) path = this.file.dataDirectory;
    else path = this.file.externalDataDirectory;
    var nomeFile : string = fileInfo.key;
    nomeFile = nomeFile.replace(/\//g, "-");
    await this.download(fileInfo.value)
      .subscribe(
      (data) => { // Success
        if(this.platform.is("ios"))
        {
          this.fileScaricati.push(fileInfo.value);
          this.count++;
        }
        else
        this.file.writeFile(path, nomeFile, data, { replace: true }).then((fileEntry: FileEntry) => {
          this.fileScaricati.push(fileEntry.toURL());
          this.count++;
        },
        (error) =>{
          this.count++;
          console.log(error);
          this.presentAlert("Avviso", "", 'Errore durante il salvataggio del file:' + nomeFile, ["OK"]);
        }
      );
    });
  }

  shareDocumento(fileUrl: string, nomeFile: string)
  {
    var path = "";
    if(this.platform.is("ios")) path = this.file.dataDirectory;
    else path = this.file.externalDataDirectory;
    nomeFile = nomeFile.replace(/\//g, "-");
    this.showLoading();
    this.download(fileUrl)
      .subscribe(
      (data) => { // Success
        this.file.writeFile(path, nomeFile, data, { replace: true }).then((fileEntry: FileEntry) => {
          console.log("File created!");
          this.closeLoading();
          this.socialSharing.share(null, null, fileEntry.toURL(), null).then(() => {
            console.log("File condiviso con successo!");
          }).catch((e) => {
            this.presentAlert("Avviso", "", 'Errore durante la condivisione del file', ["OK"]);
            console.error(e);
          });
        },
        (error) =>{
          console.error(error);
        }
      );
    });
  }

  async chiediBCall()
  {
    var id = await this.getIdUser();
    var isCliente = await this.getIsCliente();
    var param = "";
    if(isCliente) param = UtilService.encodeBody({id: id, gruppoStruttura:environment.struttura});
    else
    {
      var idCliente = AuthService.clienteSelezionato.id;
      param = UtilService.encodeBody({id: idCliente, idReferente:id, gruppoStruttura:environment.struttura});
    }
    return this.httpClient.post<ParereResponse>(this.httpClientDataService.BASE_ADDRESS+'/intranet/chiediBCall.do', param, this.httpClientDataService.httpOptions)
    .pipe(
      catchError(this.handleError),
      tap( (res:  ParereResponse ) => {

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

  downloadDocumento(fileUrl: string, nomeFile: string)
  {
    var path = "";
    if(this.platform.is("ios")) path = this.file.dataDirectory;
    else path = this.file.externalDataDirectory;
    nomeFile = nomeFile.replace(/\//g, "-");
    this.showLoading();
    this.download(fileUrl)
      .subscribe(
      (data) => { // Success
        this.file.writeFile(path, nomeFile, data, { replace: true }).then((fileEntry: FileEntry) => {
          console.log("File created!");
          this.closeLoading();
          //this.presentAlert("Avviso", "", 'File Salvato: '+fileEntry.toURL(), ["OK"]);
          //Open with File Opener plugin
          let fileExtn=nomeFile.split('.').reverse()[0];
          let fileMIMEType=UtilService.getMIMEtype(fileExtn);
          this.fileOpener.open(fileEntry.toURL(), fileMIMEType)
          .then(() => {
            console.log('File is opened');
          })
          .catch(e => {
            this.presentAlert("Avviso", "", 'Apertura file in errore', ["OK"]);
            console.log('Error openening file', e);
          });
        
        },
        (error) =>{
          console.error(error);
        }
      );
    });
  }

  stampaErrore(text: string, error)
  {
    if(error != null && error.errorMsg != null) console.log(text+": "+error.errorMsg);
    else if(error!=null) console.log(text+": "+error);
    else console.log(text);
    this.presentAlert("Errore", "", text, ["OK"]);
  }

  stampaAvviso(text: string)
  {
    this.presentAlert("Avviso", "", text, ["OK"]);
  }

  stampaSuccesso(text: string)
  {
    this.presentAlert("Successo", "", text, ["OK"]);
  }

  download(url)
  {
    return this.httpClient.get(url, {responseType: "blob"});
  }

  async apriPagina(pagina:string)
  {
    if(AuthService.isClienteLoggato && (pagina != 'notifiche' && pagina != 'change-password')) pagina = 'notifiche';
    switch(pagina)
    {
      case "preview-home":
      {        
        UtilService.titoloPagina = '';
        this.router.navigateByUrl('home/preview-home');
        break;
      }
      case "home":
      {
        
        UtilService.titoloPagina = '';
        this.router.navigateByUrl('home/index');
        break;
      }
      case "documenti":
      {
        this.translate.get('titolo_documenti').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/documenti');
        break;
      }
      case "interviste":
      {
        this.translate.get('interviste_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/interviste');
        break;
      }
      case "pareri":
      {
        this.translate.get('parere_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/parere');
        break;
      }
      case "segreteria":
      {
        this.translate.get('segreteria_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/segreteria');
        break;
      }
      case "bi":
      {
        this.router.navigateByUrl('home/bi');
        break;
      }
      case "change-password":
      {
        this.translate.get('change_password').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/change-pwd');
        break;
      }
      case "notifiche":
      {
        //var idReferente = await this.getIdUser();
        this.translate.get('notifiche_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/notifiche');
        break;
      }
      case "calendarioCorsi":
      {
        this.translate.get('calendario_corsi_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/calendario-corsi');
        break;
      }
      case "mieiCorsi":
      {
        this.translate.get('miei_corsi_titolo').subscribe(
          value => {
            UtilService.titoloPagina = value;
          });
        this.router.navigateByUrl('home/miei-corsi');
        break;
      }
    }
  }

  pushNotification(idReferente)
  {
    if(this.platform.is("desktop")) return;
    PushNotifications.requestPermissions().then(result => {
      if (result.receive === 'granted') {
        // Register with Apple / Google to receive push via APNS/FCM
        PushNotifications.register();
        this.continuePush(idReferente);
      } else {
        this.presentAlert("Errore", "", "Non hai il permesso di accedere alle push notification", ["OK"]);
        console.log('We do not have permission to send push notifications');
      }
    });
    /*this.push.hasPermission()
    .then((res: any) => {

      if (res.isEnabled || this.platform.is("ios")) {
        this.continuePush(idReferente);
      } else {
        this.presentAlert("Errore", "", "Non hai il permesso di accedere alle push notification", ["OK"]);
        console.log('We do not have permission to send push notifications');
      }

    });*/
  }

  continuePush(idReferente)
  {
    /*const options: PushOptions = {
      android: {
      },
      ios: {
          alert: 'true',
          badge: true,
          sound: 'false'
      },
      windows: {},
      browser: {}
    }

    const pushObject: PushObject = this.push.init(options);
    pushObject.on('registration').subscribe((registration: any) =>{
      this.getPushRegistrationId().then(id => {
        this.savePushRegistrationId(registration.registrationId, idReferente);
      });
    }
    );*/

    PushNotifications.addListener('registration',
      (token: Token) => {
        this.getPushRegistrationId().then(id => {
          this.savePushRegistrationId(token.value, idReferente);
        });
      }
    );

    PushNotifications.addListener('pushNotificationReceived',
      (notification: PushNotificationSchema) => {
        this.presentAlert(notification.title, "", notification.body, ["OK"]);
      }
    );

    PushNotifications.addListener('pushNotificationActionPerformed',
      (notification: ActionPerformed) => {
        UtilService.isNotificaResume = true;
        //this.presentAlert(notification.notification.title+ " coldstart", "", notification.notification.body, ["OK"]);
        this.initConfig(true, "notifiche");
      }
    );

    /*pushObject.on('notification').subscribe((data: any) =>{
      if(data.additionalData.coldstart){
        this.presentAlert(data.title+ " coldstart", "", data.message, ["OK"]);
        this.initConfig(true, "notifiche");
      }
      else this.presentAlert(data.title, "", data.message, ["OK"]);
    });*/

    /*pushObject.on('error').subscribe((error: any) =>{
      console.log("Errore durante le notifiche: "+error);
    });*/
    PushNotifications.addListener('registrationError',
      (error: any) => {
        console.log("Errore durante le notifiche: "+error);
      }
    );
  }

  savePushRegistrationId(id:string, idReferente)
  {
    //Spedizione registrationId al gestionale insieme al sapere se android o iphone
    let piattaforma:String = "";
    if(this.platform.is("android")) piattaforma = "android";
    else if(this.platform.is("ios")) piattaforma ="ios";
    else return;
    if(AuthService.isClienteLoggato) this.sendRegistration(idReferente, piattaforma, id, false).subscribe((res: ParereResponse)=>{});
    else this.sendRegistration(idReferente, piattaforma, id, true).subscribe((res: ParereResponse)=>{});
    UtilService.pushRegistrationId = id;
    this.storage.set("push_registration_id", id);
  }

  sendRegistration(idReferente: string, piattaforma:String, registrationId: String, is_referente: boolean)
  {
    var param = UtilService.encodeBody({referenteId: idReferente, tipoCellulare:piattaforma, registrationId: registrationId, is_referente: is_referente});
    return this.httpClient.post<ParereResponse>(this.httpClientDataService.BASE_ADDRESS+'/intranet/pushRegistration.do', param, this.httpClientDataService.httpOptions)
   .pipe(
      catchError(this.handleError),
      tap( (res:  ParereResponse ) => {

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

  errorRespose: ErrorResponse; 

  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);
  };

  getPushRegistrationId()
  {
    return this.storage.get("push_registration_id").then((data)=>{
      UtilService.pushRegistrationId = data;
      return data;
    });
  }

  onResumeSubscription;
  firstResume : boolean = true;
  firstPause : boolean = true;
  primaRestart: boolean = true;
  static isNotificaResume : boolean;

  setResume() {
    this.onResumeSubscription = this.platform.resume.subscribe(async () => {
      if(!this.firstResume) {
        this.initConfig(true, "notifiche");
        this.onResumeSubscription.unsubscribe();
        this.onResumeSubscription
        console.log('resumed');
        this.firstPause = true;
      }
    });   
  }

  async initConfig(resume:boolean, nextPage)
  {
    var state = await this.syncIsLoggedIn();
    if(this.firstResume)
    {
      
      if(this.platform.is("android"))
        this.platform.pause.subscribe(async () => {
          if(!this.firstPause) this.setResume();
          this.firstPause = false;
          this.firstResume = false;
          console.log('paused');
        });
    }
    if (state) {
      AuthService.isClienteLoggato = await this.getIsCliente();
      if(!this.platform.is('desktop') && !resume)
      {
        var idReferente = await this.getIdUser();
        this.pushNotification(idReferente);
      }
      this.redirectToFirstPage(nextPage);
    }
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      if(!navigator.onLine)
      {
        this.router.navigate(['error']);
        this.presentAlert("Errore", "", "Dispositivo non connesso alla rete", ["OK"]);
      }
      else
      {
        if(this.platform.is("android"))
        {
         this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.INTERNET).then(
            result => {
              console.log('Has permission?',result.hasPermission);
              this.androidPermissions.requestPermissions([this.androidPermissions.PERMISSION.INTERNET, 
                this.androidPermissions.PERMISSION.ACCESS_NETWORK_STATE, this.androidPermissions.PERMISSION.GET_ACCOUNTS,
                this.androidPermissions.PERMISSION.RECEIVE_WAP_PUSH]);
              /*if(!result.hasPermission)
              {
                this.androidPermissions.requestPermissions([this.androidPermissions.PERMISSION.INTERNET, this.androidPermissions.PERMISSION.ACCESS_NETWORK_STATE, this.androidPermissions.PERMISSION.GET_ACCOUNTS]);
              }*/
            },
            err => 
            { 
              this.presentAlert("Messaggio", "", "Richiesta Permesso", ["OK"]);
              this.androidPermissions.requestPermissions([this.androidPermissions.PERMISSION.INTERNET, this.androidPermissions.PERMISSION.GET_ACCOUNTS]);
            }
          );
        }
       

        /*this.authService.isLoggedIn().then(state => {
          if (!state) {
            this.router.navigate(['login']);
          }
        });*/
      }
    });
  }

  async redirectToFirstPage(nextPage) {
    var idReferente = null;
    while(idReferente == null) idReferente = await this.getIdUser();
    AuthService.isClienteLoggato = await this.getIsCliente();
    if(AuthService.isClienteLoggato) this.apriPagina(nextPage);
    else
      this.notificheService.isNotificheNonViste(idReferente, environment.struttura).subscribe((res: ParereResponse)=>{
        if(res.error){
          this.router.navigate(['home']);
          EventsService.setCaricaDati();
        }
        else 
        {
          if(res.autorizzato && !this.startup && UtilService.isNotificaResume)
          { 
            EventsService.setUpdateStrutture();
            UtilService.redirectToNotifiche = true;
            this.apriPagina(nextPage);
          }
          else{
            if(res.autorizzato && this.startup && this.primaRestart)
            {
              this.primaRestart = false;
              this.startup = false;
              UtilService.redirectToNotifiche = true;
              this.router.navigate(['home']);
              EventsService.setCaricaDati();
            }
            else{
              this.router.navigate(['home']);
              EventsService.setCaricaDati();
            }
          }
        }
      },
      (error: ErrorResponse) => {
        this.router.navigate(['home']);
        EventsService.setCaricaDati();
      });
  }

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

  async getIdUser()
  {
    return await this.storage.get("idUser");
  }

  async isNotResume()
  {
    return await this.storage.get("notResume");
  }

  async getIsCliente()
  {
    return await this.storage.get("isCliente");
  }
}
