import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router } from '@angular/router';
import { LocationsManagementComponent } from './locations-management/locations-management.component';
import { OccupationManagementComponent } from './occupation-management/occupation-management.component';
import { lastValueFrom } from 'rxjs';
import { EquipmentManagementService } from 'src/app/services/equipment-management.service';
import { EquipmentDetails, EquipmentDetailsResponse, EquipmentsListItem, EquipmentsListResponse, FamiliesListItem, FamiliesListResponse, PendingEquipmentsListItem, PendingEquipmentsListResponse, SubfamiliesListItem, SubfamiliesListResponse } from 'src/app/interfaces/equipment-management.interface';
import { EncService } from 'src/app/services/enc/enc.service';

@Component({
  selector: 'app-equipment-management',
  templateUrl: './equipment-management.component.html',
  styleUrls: ['./equipment-management.component.css']
})
export class EquipmentManagementComponent implements OnInit {
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;

  pendingEquipments: PendingEquipmentsListItem[];
  families: FamiliesListItem[];
  subfamilies: SubfamiliesListItem[];
  equipmentsBySubfamily: EquipmentsListItem[];

  currentLevel: number;
  equipmentStates = {DE: 'Detenido', DP: 'Detenido parcialmente', EF: 'En funcionamiento'};
  parentEquipmentDetails: EquipmentDetails | null;
  codeTypes: Map<string, string>;

  constructor(
    private _router: Router,
    private _dialog: MatDialog,
    private _equipmentManagementService: EquipmentManagementService,
    private _encService: EncService,
    private _activatedRoute: ActivatedRoute,
  ) { 
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";

    this.pendingEquipments = [];
    this.families = [];
    this.subfamilies = [];
    this.equipmentsBySubfamily = [];

    this.currentLevel = 1;
    this.parentEquipmentDetails = null;
    this.codeTypes = new Map([
      ['1', 'General'],
      ['2', 'PCC'],
      ['3', 'Origen y destino para líneas y enlaces'],
      ['4', 'Origen y destino para estaciones y edificios'],
      ['5', 'Tren'],
      ['6', 'Origen y destino mixto'],
    ]);
  }

  ngOnInit(): void {
    this._activatedRoute.queryParams.subscribe(params => {
      this.init(params);
    });
  }

  async init(params: any){
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";

    let family = params['family'];
    if(family == undefined){
      this.currentLevel = 1;
      this.getFamilies();
      return;
    }

    let subfamily = params['subfamily'];
    if(subfamily == undefined){
      this.currentLevel = 2;
      this.getSubfamilies(family);
      return;
    }

    let arborescence = params['arborescence'];
    if(arborescence == undefined){
      this.currentLevel = 3;
      this.getEquipmentsBySubfamily(family, subfamily);
      return;
    }

    let arborescenceStr = window.atob(arborescence);
    let arborescenceArr = JSON.parse(arborescenceStr);

    //Pendiente construir la ruta de la arborescencia

    arborescenceArr.reverse();
    let lastParent = arborescenceArr[0];
    this.currentLevel = 4;
    this.getEquipmentsByParent(lastParent);
  }

  manageFamilies(){
    this._router.navigate(['sam/GEEQ/DFSU']);
  }

  manageLocations(){
    this._dialog.open(LocationsManagementComponent, {
      width: '520px',
    });
  }

  async openEquipmentForm(action: string, id: string = '-'){
    this._router.navigate(['sam/GEEQ/REEQ'], {
      queryParams: {
        action: action,
      }
    });
  }

  manageOccupations(){
    this._dialog.open(OccupationManagementComponent, {
      disableClose: true,
      width: '840px',
    })
  }

  async getPendingEquipments(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let pendingEquipments: PendingEquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultPending(idUser, 1));

      this.hasError = pendingEquipments.error;
      this.errorStr = pendingEquipments.msg;

      if(!this.hasError){
        let equipments: PendingEquipmentsListItem[] = [];
        for(const equipment of pendingEquipments.response){
          equipment.CODIGO = await this._encService.decrypt(equipment.CODIGO);
          equipment.TIPO_EQUIPAMIENTO = await this._encService.decrypt(equipment.TIPO_EQUIPAMIENTO);
          equipment.MODELO_EQUIPAMIENTO = await this._encService.decrypt(equipment.MODELO_EQUIPAMIENTO);

          let galleryArr = JSON.parse(equipment.GALERIA_IMAGENES as string);
          let gallery: string[] = [];
          for(const imageStr of galleryArr){
            let imageDec = await this._encService.decrypt(imageStr);
            gallery.push(imageDec);
          }

          equipment.GALERIA_IMAGENES = gallery;
          equipments.push(equipment);
        }

        this.pendingEquipments = equipments;
      }

      this.isLoading = false;
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getFamilies(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let families: FamiliesListResponse = await lastValueFrom(this._equipmentManagementService.familyConsult(idUser, 1));

      this.hasError = families.error;
      this.errorStr = families.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let familiesArr: FamiliesListItem[] = [];
        for(const family of families.response){
          let codeDec = await this._encService.decrypt(family.CODIGOFAMILIA);
          family.NOMBREFAMILIA = `${family.NOMBREFAMILIA} (${codeDec})`;

          familiesArr.push(family);
        }

        this.families = familiesArr;
        this.getPendingEquipments();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getSubfamilies(family: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let subfamilies: SubfamiliesListResponse = await lastValueFrom(this._equipmentManagementService.subfamilyConsult(family, idUser, 1));

      this.hasError = subfamilies.error;
      this.errorStr = subfamilies.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let subfamiliesArr: SubfamiliesListItem[] = [];
        for(const subfamily of subfamilies.response){
          let codeDec = await this._encService.decrypt(subfamily.CODIGOSUBFAMILIA);
          subfamily.NOMBRESUBFAMILIA = `${subfamily.NOMBRESUBFAMILIA} (${codeDec})`;

          subfamiliesArr.push(subfamily);
        }

        this.subfamilies = subfamiliesArr;
        this.getPendingEquipments();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getEquipmentsBySubfamily(family: string, subfamily: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let equipmentsBySubfamily: EquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultBySubfamily(
        family, 
        subfamily, 
        idUser, 
        1
      ));

      this.hasError = equipmentsBySubfamily.error;
      this.errorStr = equipmentsBySubfamily.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let equipments: EquipmentsListItem[] = [];
        for(const equipment of equipmentsBySubfamily.response){
          let idDec = await this._encService.decrypt(equipment.ID_EQUIPO);
          equipment.MODELO = `${equipment.MODELO} (${idDec})`;

          let functionState = this.equipmentStates[equipment.ESTADO_FUNCIONAMIENTO as never];
          equipment.ESTADO_FUNCIONAMIENTO = `${functionState} (${equipment.ESTADO_FUNCIONAMIENTO})`;

          let galleryArr = JSON.parse(equipment.GALERIA_IMAGENES as string);
          let images: string[] = [];
          for(const image of galleryArr){
            let uriDec = await this._encService.decrypt(image);
            images.push(uriDec);
          }

          equipment.GALERIA_IMAGENES = images;
          equipments.push(equipment);
        }

        this.equipmentsBySubfamily = equipments;
        this.getPendingEquipments();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }
    }
  }

  async getEquipmentsByParent(parent: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let parentEquipments: EquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultByParent(
        parent, 
        idUser, 
        1
      ));

      this.hasError = parentEquipments.error;
      this.errorStr = parentEquipments.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        let equipments: EquipmentsListItem[] = [];
        for(const equipment of parentEquipments.response){
          let idDec = await this._encService.decrypt(equipment.ID_EQUIPO);
          equipment.MODELO = `${equipment.MODELO} (${idDec})`;

          let functionState = this.equipmentStates[equipment.ESTADO_FUNCIONAMIENTO as never];
          equipment.ESTADO_FUNCIONAMIENTO = `${functionState} (${equipment.ESTADO_FUNCIONAMIENTO})`;

          let galleryArr = JSON.parse(equipment.GALERIA_IMAGENES as string);
          let images: string[] = [];
          for(const image of galleryArr){
            let uriDec = await this._encService.decrypt(image);
            images.push(uriDec);
          }

          equipment.GALERIA_IMAGENES = images;
          equipments.push(equipment);
        }

        this.equipmentsBySubfamily = equipments;
        this.getEquipmentDetails(parent);
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  async getEquipmentDetails(equipmentCode: string){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let equipment: EquipmentDetailsResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultOnly(
        equipmentCode,
        idUser, 
        1
      ));

      this.hasError = equipment.error;
      this.errorStr = equipment.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        equipment.response.CODIGO = await this._encService.decrypt(equipment.response.CODIGO);
        equipment.response.DOCUMENTOS = JSON.parse(equipment.response.DOCUMENTOS as string);
        
        let images = JSON.parse(equipment.response.GALERIA_IMAGENES as string);
        let imagesArr: string[] = [];
        for(const image of images){
          let imageDec = await this._encService.decrypt(image);
          imagesArr.push(imageDec);
        }
        
        equipment.response.GALERIA_IMAGENES = imagesArr;

        let codeHistory = JSON.parse(equipment.response.HISTORIAL_CODIGOS as string);
        let codeHistoryArr: string[] = [];
        for(const code of codeHistory){
          let codeDec = await this._encService.decrypt(code);
          codeHistoryArr.push(codeDec);
        }
        
        equipment.response.HISTORIAL_CODIGOS = codeHistoryArr;
        equipment.response.ID_EQUIPAMIENTO = await this._encService.decrypt(equipment.response.ID_EQUIPAMIENTO);
        equipment.response.MODELO = await this._encService.decrypt(equipment.response.MODELO);
        
        equipment.response.TIPO_EQUIPAMIENTO = await this._encService.decrypt(equipment.response.TIPO_EQUIPAMIENTO);

        equipment.response.TIPO_CODIGO = `${this.codeTypes.get(equipment.response.TIPO_CODIGO)} (${equipment.response.TIPO_CODIGO})`;
        
        this.parentEquipmentDetails = equipment.response;
        this.getPendingEquipments();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

      this.hasError = true;
      this.isLoading = false;
    }
  }

  shouldRefresh(event: any){
    if(event == 'refresh'){
      this.getPendingEquipments();
    }
  }

  familyClicked(event: any){
    this.navigate('family', event);
  }

  subfamilyClicked(event: any){
    this.navigate('subfamily', event);
  }

  private navigate(type: string, code: string){
    if(type == 'family'){
      this._router.navigate(['sam/GEEQ'], {
        queryParams: {
          family: code
        }
      })
    }else if(type == 'subfamily'){
      let currentRoute = window.location.href;
      let routeArr = currentRoute.split('?');
      let family = routeArr.filter(item => item.includes('family'))[0].replace('family=', '');

      this._router.navigate(['sam/GEEQ'], {
        queryParams: {
          family: family,
          subfamily: code
        }
      });
    }else{
      let currentRoute = window.location.href;
      let routeArr = currentRoute.split('?').reverse();
      let paramsArr = routeArr[0].split('&');

      let family = paramsArr.filter(item => item.includes('family'))[0].replace('family=', '');
      let subfamily = paramsArr.filter(item => item.includes('subfamily'))[0].replace('subfamily=', '');

      let arborescenceFilt = paramsArr.filter(item => item.includes('arborescence'));
      let arborescenceArr = [];
      if(arborescenceFilt.length > 0){
        console.log(arborescenceFilt);
        return;
      }

      arborescenceArr.push(code);
      let arborescence = window.btoa(JSON.stringify(arborescenceArr));

      this._router.navigate(['sam/GEEQ'], {
        queryParams: {
          family: family,
          subfamily: subfamily,
          arborescence: arborescence
        }
      });
    }
  }

  goBack(steps: number){
    window.history.go(steps * -1);
  }

  openChildren(event: any){
    this.navigate('equipment', event);
  }
}
