import { Component, Inject, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { 
  CarAreasListItem, 
  CarAreasListResponse, 
  EquipmentDetailsResponse, 
  EquipmentsListItem, 
  EquipmentsListResponse, 
  FamiliesListItem, 
  FamiliesListResponse, 
  LocationsListItem, 
  LocationsListResponse, 
  OccupationsListItem, 
  OccupationsListResponse, 
  SubfamiliesListItem, 
  SubfamiliesListResponse, 
  TrainElementsListItem, 
  TrainElementsListResponse, 
  TrainOccupationsListItem, 
  TrainOccupationsListResponse
} from '../../../interfaces/equipment-management.interface';
import { GetProvidersActives, ResponseDataGetProvidersActives } from '../../../interfaces/acquisition-management/provider.interface';
import { MatTableDataSource } from '@angular/material/table';
import { TempFileInfo } from '../../../interfaces/temp-file-info.interface';
import { debounceTime, distinctUntilChanged, filter, lastValueFrom, map, Observable, startWith, switchMap, tap } from 'rxjs';
import { ActivatedRoute } from '@angular/router';
import { ResourcesService } from '../../../services/resources.service';
import { EquipmentManagementService } from '../../../services/equipment-management.service';
import { EncService } from '../../../services/enc.service';
import { MatDialog } from '@angular/material/dialog';
import { GdelService } from '../../../services/gdel.service';
import { ProviderService } from '../../../services/acquisition-management/provider.service';
import { FatherLoaderComponent } from './father-loader/father-loader.component';
import { LocateCarAreaComponent } from './locate-car-area/locate-car-area.component';
import { SearchEquipmentComponent } from './search-equipment/search-equipment.component';
import { LocatePccComponent } from './locate-pcc/locate-pcc.component';
import { availableFiles } from '../../../../environments/environment.prod';
import { LocateCarComponent } from './locate-car/locate-car.component';
import { GraphicEquipmentSearchComponent } from '../graphic-equipment-search/graphic-equipment-search.component';
import { DOCUMENT } from '@angular/common';

@Component({
    selector: 'app-new-equipment',
    templateUrl: './new-equipment.component.html',
    styleUrl: './new-equipment.component.css',
    standalone: false
})
export class NewEquipmentComponent implements OnInit {
  action: string;
  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  generatedTag: string;
  formGroup: FormGroup;
  disableAttachActions: boolean;
  warrantyStartDate: Date | null;
  warrantyEndDate: Date | null;
  screenSize: number;
  locatingCoords: boolean;
  coordsType: string;

  locationsArr: LocationsListItem[];
  levelsArr: any[];
  levelsArrAux: any[];
  occupations: OccupationsListItem[];
  familiesArr: FamiliesListItem[];
  subfamiliesArr: SubfamiliesListItem[];
  statesArr: any[];
  trainOccupations: TrainOccupationsListItem[];
  carAreas: CarAreasListItem[];
  trainElements: TrainElementsListItem[];
  equipments: EquipmentsListItem[];
  equipmentsStr: string[];
  arrProvider: Array<GetProvidersActives>;
  providersStr: string[];
  autoCompleteEquipments: string[];
  additionalCodes: string[];

  searchingSubfamilies: boolean;
  searchingCarAreas: boolean;
  searchingEquipments: boolean;

  codeControlsStr = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 'originElementControl', 'originCoordsControl', 
  'originCoordsPlaneControl', 'familyControl', 'subfamilyControl', 'statusControl', 'equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl', 
  'pccIntersectionControl', 'pccPositionControl', 'originKilometersControl', 'destinyLocationControl', 'destinyLevelControl', 'destinyOccupationControl', 
  'destinyElementControl', 'destinyKilometersControl', 'destinyCoordsControl', 'trainAreaControl', 'mixOriginControl', 'mixDestinyControl'];
  equipmentStates = ['Adquisición', 'Stock', 'Traslado', 'Instalación', 'Reparación', 'Disposición'];
  viaLabels = ['sobre túnel', 'techo - túnel', 'túnel', 'vía', 'debajo de vía'];

  imagesDataSource: MatTableDataSource<TempFileInfo>;
  imagesDisplayedColumns = ['name', 'size', 'acciones'];
  attachedImages: TempFileInfo[];
  uploadingImages: boolean;
  equipmentTypeDisabled: boolean;
  equipmentType: string;

  documentsDataSource: MatTableDataSource<TempFileInfo>;
  documentsDisplayedColumns = ['name', 'size', 'acciones'];
  attachedDocuments: TempFileInfo[];
  uploadingDocuments: boolean;

  filteredEquipments?: Observable<string[]>;
  filteredProviders?: Observable<string[]>;

  pccElements = [
    {element: 'PDC',                                     code: 'XXPDC', color: '#337a91'},
    {element: 'BAT',                                     code: 'XXBAT', color: '#8e3596'},
    {element: 'SAP/IHM OA',                              code: 'SAIOA', color: '#3ba896'},
    {element: 'UPS',                                     code: 'XXUPS', color: '#d4735b'},
    {element: 'PIU/DDP',                                 code: 'PIUDD', color: '#065240'},
    {element: 'ODF',                                     code: 'XXODF', color: '#94e687'},
    {element: 'SRV-COMMS PCC-A',                         code: 'SRCPA', color: '#4dd907'},
    {element: 'CCTV',                                    code: 'XCCTV', color: '#3d36ba'},
    {element: 'SRV-COMMS PCC-B',                         code: 'SRCPB', color: '#a9ba36'},
    {element: 'LTE',                                     code: 'XXLTE', color: '#36ba4e'},
    {element: 'AC',                                      code: 'XXXAC', color: '#ba4336'},
    {element: 'SRV-COMMS PCC-C',                         code: 'SRCPC', color: '#a1107f'},
    {element: 'TEL/GDA',                                 code: 'TELGD', color: '#173306'},
    {element: 'SCADA E&M',                               code: 'SCAEM', color: '#47edcc'},
    {element: 'CLK/CDA',                                 code: 'CLKCD', color: '#1629f7'},
    {element: 'INTERRUPTOR ELECTROMAGNÉTICO 3x1600 AMP', code: 'IE316', color: '#f0f716'},
    {element: 'RMS',                                     code: 'XXRMS', color: '#f71629'},
    {element: 'LTE-B',                                   code: 'XLTEB', color: '#8e16f7'},
    {element: 'TRANSFORMADOR TIPO SECO 500 KVA',         code: 'TTS5K', color: '#f716e8'},
    {element: 'ARMARIOS RECUPERACIÓN DE MANDO L1 A L6',  code: 'ARM16', color: '#f78316'},
    {element: 'MDF',                                     code: 'XXMDF', color: '#167cf7'},
    {element: 'COBRE',                                   code: 'COBRE', color: '#205266'},
    {element: 'RED',                                     code: 'XXRED', color: '#662022'},
    {element: 'TABLERO A',                               code: 'TABLA', color: '#cfc763'},
    {element: 'CCTV L1 A L6',                            code: 'CCT16', color: '#e62e34'},
    {element: 'RED C Y S L1 A L6',                       code: 'RCS16', color: '#065240'},
    {element: 'TRACCIÓN',                                code: 'TRACC', color: '#94e687'},
    {element: 'TABLERO P',                               code: 'TABLP', color: '#05c9f0'},
    {element: 'DISTRIBUCIÓN DE ENERGÍA L2',              code: 'DIEL2', color: '#ba8336'},
    {element: 'TABLERO B',                               code: 'TABLB', color: '#a9ba36'},
    {element: 'TELECOM L2',                              code: 'TELL2', color: '#36ba4e'},
    {element: 'SERVIDOR BASE DE DATOS L2',               code: 'SBDL2', color: '#ba4336'},
    {element: 'SERVIDOR DE APLICACIONES L2',             code: 'SEAL2', color: '#a1107f'},
    {element: 'DISTRIBUCIÓN DE ENERGÍA L3',              code: 'DIEL3', color: '#c781b7'},
    {element: 'TELECOM L3',                              code: 'TELL3', color: '#173306'},
    {element: 'SERVIDOR BASE DE DATOS L3',               code: 'SBDL3', color: '#06332a'},
    {element: 'SERVIDOR DE APLICACIONES L3',             code: 'SEAL3', color: '#47edcc'},
    {element: 'DISTRIBUCIÓN DE ENERGÍA L4',              code: 'DIEL4', color: '#1629f7'},
    {element: 'TELECOM L4',                              code: 'TELL4', color: '#f716e8'},
    {element: 'SERVIDOR BASE DE DATOS L4',               code: 'SBDL4', color: '#f78316'},
    {element: 'SERVIDOR DE APLICACIONES L4',             code: 'SEAL4', color: '#3cf716'},
    {element: 'DISTRIBUCIÓN DE ENERGÍA L5',              code: 'DIEL5', color: '#167cf7'},
    {element: 'TELECOM L5',                              code: 'TELL5', color: '#576620'},
    {element: 'SERVIDOR BASE DE DATOS L5',               code: 'SBDL5', color: '#205266'},
    {element: 'SERVIDOR DE APLICACIONES L5',             code: 'SEAL5', color: '#382066'},
    {element: 'TELECOM L6',                              code: 'TELL6', color: '#662022'},
    {element: 'SERVIDOR BASE DE DATOS L6',               code: 'SBDL6', color: '#827474'},
    {element: 'SERVIDOR DE APLICACIONES L6',             code: 'SEAL6', color: '#b4aae6'},
    {element: 'DISTRIBUCIÓN DE ENERGÍA L6',              code: 'DIEL6', color: '#120d2e'},
  ];

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _activatedRoute: ActivatedRoute,
    private _resourcesService: ResourcesService,
    private _equipmentManagementService: EquipmentManagementService,
    private _encService: EncService,
    private _dialog: MatDialog,
    private _gdelService: GdelService,
    private _providersService: ProviderService,
  ) {
    this.action = "";
    this.isLoading = true;
    this.hasError = false;
    this.errorStr = "";
    this.generatedTag = "";
    this.disableAttachActions = false;
    this.warrantyStartDate = null;
    this.warrantyEndDate = null;
    this.screenSize = window.innerWidth;
    this.locatingCoords = false;
    this.coordsType = '';

    this.locationsArr = [];
    this.levelsArr = [];
    this.levelsArrAux = [];
    this.occupations = [];
    this.familiesArr = [];
    this.subfamiliesArr = [];
    this.statesArr = [];
    this.trainOccupations = [];
    this.carAreas = [];
    this.trainElements = [];
    this.equipments = [];
    this.equipmentsStr = [];
    this.arrProvider = [];
    this.providersStr = [];
    this.autoCompleteEquipments = [];
    this.additionalCodes = [''];

    this.searchingSubfamilies = false;
    this.searchingCarAreas = false;
    this.searchingEquipments = false;

    this.imagesDataSource = new MatTableDataSource();
    this.attachedImages = [];
    this.uploadingImages = false;
    this.equipmentTypeDisabled = false;
    this.equipmentType = '';

    this.documentsDataSource = new MatTableDataSource();
    this.attachedDocuments = [];
    this.uploadingDocuments = false;

    this.formGroup = new FormGroup({
      //Controles generales
      hierarchyControl: new FormControl('', Validators.required),
      fatherControl: new FormControl({disabled: true, value: ''}, Validators.required),
      codeTypeControl: new FormControl({disabled: true, value: ''}, Validators.required),
      mixOriginControl: new FormControl({disabled: true, value: ''}, Validators.required),
      mixDestinyControl: new FormControl({disabled: true, value: ''}, Validators.required),
      //Controles usado en todos los casos
      lineControl: new FormControl({disabled: true, value: '01'}, Validators.required),
      originLocationControl: new FormControl({disabled: true, value: ''}, Validators.required),
      originLevelControl: new FormControl({disabled: true, value: ''}, Validators.required),
      originOccupationControl: new FormControl({disabled: true, value: ''}, Validators.required),
      originElementControl: new FormControl({disabled: true, value: ''}, Validators.required),
      originCoordsControl: new FormControl({disabled: true, value: ''}, Validators.required),
      originCoordsPlaneControl: new FormControl({disabled: true, value: ''}, Validators.required),
      familyControl: new FormControl({disabled: true, value: ''}, Validators.required),
      subfamilyControl: new FormControl({disabled: true, value: ''}, Validators.required),
      statusControl: new FormControl({disabled: true, value: ''}, Validators.required),
      equipmentTypeControl: new FormControl({disabled: true, value: ''}, [Validators.required, Validators.maxLength(150)]),
      equipmentModelControl: new FormControl({disabled: true, value: ''}, [Validators.required, Validators.maxLength(75)]),
      equipmentIDControl: new FormControl({disabled: true, value: 'XXXXXX'}),
      //Controles específicos para PCC
      pccIntersectionControl: new FormControl({disabled: true, value: '',}, Validators.required),
      pccPositionControl: new FormControl({disabled: true, value: ''}, [Validators.required, Validators.maxLength(2)]),
      //Controles para los casos de origen - destino
      originKilometersControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyLocationControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyLevelControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyOccupationControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyElementControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyKilometersControl: new FormControl({disabled: true, value: ''}, Validators.required),
      destinyCoordsControl: new FormControl({disabled: true, value: ''}, Validators.required),
      //Controles de información complementaria
      acquisitionDateControl: new FormControl('', Validators.required),
      warrantyStartDateControl: new FormControl(this.warrantyStartDate, Validators.required),
      warrantyEndDateControl: new FormControl(this.warrantyEndDate, Validators.required),
      equipmentProviderControl: new FormControl('', Validators.required),
      serialNumberControl: new FormControl('', Validators.required),
      hasSoftwareControl: new FormControl('', Validators.required),
      softwareNameControl: new FormControl({disabled: true, value: ''}),
      softwareVersionControl: new FormControl({disabled: true, value: ''}),
      //Controles para los casos de origen - destino para estaciones y edificios
      originSequenceControl: new FormControl(''),
      destinySequenceControl: new FormControl(''),
      //Controles para los casos de tren
      trainAreaControl: new FormControl({disabled: true, value: ''}, Validators.required),
      //Controles para los casos de origen - destino mixto
      originCodePartUsed: new FormControl({disabled: true, value: 'O'}, Validators.required),
      destinyCodePartUsed: new FormControl({disabled: true, value: 'D'}, Validators.required),
    });
  }

  ngOnInit(): void {
    this._activatedRoute.queryParams.subscribe(res => {
      let action = res['action'];
      if(action == null || action == undefined || action == ''){
        this._resourcesService.openSnackBar('No se encontró ninguna acción.');
        this.goBack(1);
      }else if(action == 'edit'){
        let idEquipmentEnc = res['id'];
        if(idEquipmentEnc == null || idEquipmentEnc == undefined || idEquipmentEnc == ''){
          this._resourcesService.openSnackBar('No se encontró el ID de ningún equipamiento.');
          this.goBack(1);
        }else{
          this.action = 'Editar';
          this.init(idEquipmentEnc);
        }
      }else{
        let equipmentType = res['equipmentType'];
        if(equipmentType != undefined){
          equipmentType = decodeURI(equipmentType);

          this.formGroup.controls['equipmentTypeControl'].setValue(equipmentType);
          this.equipmentTypeDisabled = true;
          this.equipmentType = equipmentType;
        }
        
        this.action = 'Registrar';
        this.getLocations();
      }
    });

    this.formGroup.controls['hasSoftwareControl'].valueChanges.subscribe(val => {
      this.formGroup.controls['softwareNameControl'].setValue(null);
      this.formGroup.controls['softwareVersionControl'].setValue(null);

      if(val == 'Si'){
        this.formGroup.controls['softwareNameControl'].enable();
        this.formGroup.controls['softwareVersionControl'].enable();
        this.formGroup.controls['softwareNameControl'].setValidators([Validators.required]);
        this.formGroup.controls['softwareVersionControl'].setValidators([Validators.required]);
      }else{
        this.formGroup.controls['softwareNameControl'].disable();
        this.formGroup.controls['softwareVersionControl'].disable();
        this.formGroup.controls['softwareNameControl'].setValidators([]);
        this.formGroup.controls['softwareVersionControl'].setValidators([]);
      }
    });

    this.formGroup.controls['warrantyStartDateControl'].valueChanges.subscribe((selected: Date) => {
      this.warrantyStartDate = selected;
    });

    this.formGroup.controls['warrantyEndDateControl'].valueChanges.subscribe((selected: Date) => {
      this.warrantyEndDate = selected;
    });

    /*this.filteredEquipments = this.formGroup.controls['fatherControl'].valueChanges.pipe(
      startWith(''),
      map(value => this._filterEquipments(value || '')),
    );*/

    this.formGroup.controls['fatherControl'].valueChanges.pipe(
      debounceTime(300),
      distinctUntilChanged(),
      filter(value => value ? true : false),
      tap(() => this.searchingEquipments = true),
      switchMap(value => this._filterEquipments(value)),
    ).subscribe(autoCompleteList => {
      this.autoCompleteEquipments = autoCompleteList;
    });

    this.filteredProviders = this.formGroup.controls['equipmentProviderControl'].valueChanges.pipe(
      startWith(''),
      map(value => this._filterProviders(value || '')),
    );
  }

  private async _filterEquipments(value: string): Promise<string[]>{
    let equipmentsStr: string[] = [];
    let idUser = localStorage.getItem('idusuario')!;
    let equipments: EquipmentsListResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultFiltered(value, idUser, 1));

    if(equipments.error){
      this._resourcesService.openSnackBar(equipments.msg);
    }else{
      for(const equipment of equipments.response){
        let codeDec = await this._encService.decrypt(equipment.CODIGO);
        let idDec = await this._encService.decrypt(equipment.ID_EQUIPO);

        equipmentsStr.push(`${codeDec} - ${equipment.TIPO} - ${equipment.MODELO} (${idDec})`);
        equipment.CODIGO = codeDec;

        let equipmentsFilt = this.equipments.filter(item => item.CODIGO == codeDec);
        if(equipmentsFilt.length <= 0){
          this.equipments.push(equipment);
        }
      }
    }

    this.searchingEquipments = false;
    return equipmentsStr;
  }

  private _filterProviders(value: string): string[]{
    const filterValue = value.toLowerCase();
    return this.providersStr.filter(option => option.toLowerCase().includes(filterValue));
  }

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

  async init(idEquipmentEnc: string){
    //console.log(idEquipmentEnc);
  }

  async getLocations(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let locations: LocationsListResponse = await lastValueFrom(this._equipmentManagementService.locationConsult(idUser, 1));

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

      if(this.hasError){
        this.isLoading = false;
      }else{
        for(const location of locations.response){
          let locationDec = await this._encService.decrypt(location.LOCATION);
          let codeDec = await this._encService.decrypt(location.CODE);

          location.LOCATION = `${locationDec} (${codeDec})`;
          this.locationsArr.push(location);
        }

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

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

  async fillLevels(){
    for(let i = 5; i > 0; i--){
      let tagStr = `S0${i}`;
      let labelStr = `Subterráneo ${i} (${tagStr})`;
      let tagEnc = await this._encService.encrypt(tagStr);

      this.levelsArr.push({
        LABEL: labelStr,
        CODE: tagEnc
      });
    }

    for(let i = 0; i <= 15; i++){
      let tagStr = i < 10 ? `P0${i}` : `P${i}`;
      let labelStr = i == 0 ? 'Planta baja' : `Piso ${i}`;
      labelStr = `${labelStr} (${tagStr})`;

      let tagEnc = await this._encService.encrypt(tagStr);
      this.levelsArr.push({
        LABEL: labelStr,
        CODE: tagEnc
      });
    }

    this.getOccupations();
  }

  async getOccupations(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let occupations: OccupationsListResponse = await lastValueFrom(this._equipmentManagementService.occupationConsult(idUser, 1));
      
      this.hasError = occupations.error;
      this.errorStr = occupations.msg;

      if(this.hasError){
        this.isLoading = false;
      }else{
        for(const occupation of occupations.response){
          if(occupation.ESTADO == 'Activo'){
            occupation.DESCRIPCION = `${occupation.DESCRIPCION} (${occupation.OCUPACION})`;
            occupation.OCUPACION = await this._encService.encrypt(occupation.OCUPACION);
            
            this.occupations.push(occupation);
          }
        }

        this.getFamilies();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado (3).';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado (4).';
      }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{
        for(const family of families.response){
          let codeDec = await this._encService.decrypt(family.CODIGOFAMILIA);

          family.NOMBREFAMILIA = `${family.NOMBREFAMILIA} (${codeDec})`;
          if(family.ESTADO == 'Activo'){
            this.familiesArr.push(family);
          }
        }

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

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

  async fillEquipmentStates(){
    for(const state of this.equipmentStates){
      let id = state.charAt(0);
      let idEnc = await this._encService.encrypt(id);

      this.statesArr.push({
        STATUS: `${state} (${id})`,
        ID: idEnc
      });
    }

    this.getTrainOccupations();
  }

  async getTrainOccupations(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let trainOccupations: TrainOccupationsListResponse = await lastValueFrom(this._equipmentManagementService.occupationTrainConsult(idUser, 1));

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

      if(this.hasError){
        this.isLoading = false;
      }else{
        let trainOccupationsArr: TrainOccupationsListItem[] = [];
        for(const occupation of trainOccupations.response){
          let carDec = await this._encService.decrypt(occupation.CAR);
          let codeDec = await this._encService.decrypt(occupation.CODE);

          occupation.CAR = `${carDec} (${codeDec})`;
          trainOccupationsArr.push(occupation);
        }

        this.trainOccupations = trainOccupationsArr;
        this.getTrainElements();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado (7).';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado (8).';
      }else{
        this.errorStr = error.error.msg;
      }

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

  async getTrainElements(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let trainElements:TrainElementsListResponse = await lastValueFrom(this._equipmentManagementService.occupationTrainElements(idUser, 1));

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

      if(this.hasError){
        this.isLoading = false;
      }else{
        let trainElementsArr: TrainElementsListItem[] = [];
        for(const element of trainElements.response){
          let codeDec = await this._encService.decrypt(element.CODE);
          let elementDec = await this._encService.decrypt(element.ELEMENT);

          element.ELEMENT = `${elementDec} (${codeDec})`;
          trainElementsArr.push(element);
        }

        this.trainElements = trainElementsArr;
        this.getProviders();
      }
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado (9).';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado (10).';
      }else{
        this.errorStr = error.error.msg;
      }
    }
  }

  async getProviders(){
    try{
      const user: string = this._resourcesService.getUser();
      const line: number = this._resourcesService.getLineNumber();
      let providers: ResponseDataGetProvidersActives = await lastValueFrom(this._providersService.getProviderActives(user, line));

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

      if(!this.hasError){
        let providersArr: GetProvidersActives[] = [];
        let providersStrArr: string[] = [];

        for(const provider of providers.response as GetProvidersActives[]){
          providersArr.push(provider);
          providersStrArr.push(`(${provider.NUMERO_PROVEEDOR}) ${provider.RAZON_SOCIAL}`);
        }

        this.arrProvider = providersArr;
        this.providersStr = providersStrArr;
      }

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

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

  onResize():void{
    this.screenSize = window.innerWidth;
  }

  changeHierarchy(value: string){
    if(value == 'Hijo'){
      this.formGroup.controls['fatherControl'].enable();
      this.formGroup.controls['codeTypeControl'].disable();
      this.formGroup.controls['codeTypeControl'].setValue(null);
    }else{
      this.formGroup.controls['fatherControl'].setValue(null);
      this.formGroup.controls['fatherControl'].disable();
      this.formGroup.controls['codeTypeControl'].enable();
    }
  }

  verifyFather(value: string){
    let valueArr = value.split(' - ');
    if(valueArr.length == 3 && value != null && value != undefined && value != ''){
      this.getFatherDescription(valueArr[0]);
    }
  }

  private async getFatherDescription(fatherCode: string){
    let dialogRef = this._dialog.open(FatherLoaderComponent, {
      width: '420px',
      minWidth: '420px',
      disableClose: true
    });

    let equipmentFilt = this.equipments.filter(item => item.CODIGO == fatherCode);
    if(equipmentFilt.length <= 0){
      this._resourcesService.openSnackBar('El equipo padre seleccionado no existe.');
      dialogRef.close();
    }else{
      let equipmentCodeEnc = await this._encService.encrypt(equipmentFilt[0].CODIGO);
      let idUser = localStorage.getItem('idusuario')!;
      let equipment: EquipmentDetailsResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultOnly(
        equipmentCodeEnc, 
        idUser, 
        1
      ));

      if(equipment.error){
        this._resourcesService.openSnackBar(equipment.msg);
        dialogRef.close();
      }else{
        this.formGroup.controls['codeTypeControl'].setValue(equipment.response.TIPO_CODIGO);

        let originLocationArr = equipment.response.UBICACION_ORIGEN.split('(').reverse();
        let originLocation = originLocationArr[0].replace(')', '');

        for(const location of this.locationsArr){
          let codeDec = await this._encService.decrypt(location.CODE);
          if(codeDec == originLocation){
            this.formGroup.controls['originLocationControl'].setValue(`${location.CODE}-enc`);
          }
        }

        let originLevelArr = equipment.response.NIVEL_ORIGEN.split('(').reverse();
        let originLevel = originLevelArr[0].replace(')', '');

        for(const level of this.levelsArr){
          let codeDec = await this._encService.decrypt(level.CODE);
          if(originLevel == codeDec){
            this.formGroup.controls['originLevelControl'].setValue(`${level.CODE}-enc`);
          }
        }

        let originOccupationArr = equipment.response.OCUPACION_ORIGEN.split('(').reverse();
        let originOccupation = originOccupationArr[0].replace(')', '');

        for(const occupation of this.occupations){
          let occupationDec = await this._encService.decrypt(occupation.OCUPACION);
          if(occupationDec == originOccupation){
            this.formGroup.controls['originOccupationControl'].setValue(`${occupation.OCUPACION}-enc`);
          }
        }

        this.formGroup.controls['originElementControl'].setValue(equipment.response.ELEMENTO_ORIGEN);
        let familyArr = equipment.response.FAMILIA.split('(').reverse();
        let familyStr = familyArr[0].replace(')', '');

        for(const family of this.familiesArr){
          let codeDec = await this._encService.decrypt(family.CODIGOFAMILIA);
          if(codeDec == familyStr){
            this.formGroup.controls['familyControl'].setValue(`${family.CODIGOFAMILIA}-enc`);
          }
        }

        let familyEnc = await this._encService.encrypt(familyStr);
        let subfamilies: SubfamiliesListResponse = await lastValueFrom(this._equipmentManagementService.subfamilyConsult(
          familyEnc,
          idUser,
          1
        ));

        if(subfamilies.error){
          this._resourcesService.openSnackBar(subfamilies.msg);
          dialogRef.close();
          return;
        }
        
        let subfamilyArr = equipment.response.SUBFAMILIA.split('(').reverse();
        let subfamilyStr = subfamilyArr[0].replace(')', '');
        let subfamiliesArr: SubfamiliesListItem[] = [];

        for(const subfamily of subfamilies.response){
          let codeDec = await this._encService.decrypt(subfamily.CODIGOSUBFAMILIA);
          subfamily.NOMBRESUBFAMILIA = `${subfamily.NOMBRESUBFAMILIA} (${codeDec})`;

          if(codeDec == subfamilyStr){
            this.formGroup.controls['subfamilyControl'].setValue(`${subfamily.CODIGOSUBFAMILIA}-enc`);
          }

          subfamiliesArr.push(subfamily)
        };

        this.subfamiliesArr = subfamiliesArr;
        let stateArr = equipment.response.ESTADO.split('(').reverse();
        let stateStr = stateArr[0].replace(')', '');

        for(const state of this.statesArr){
          let idDec = await this._encService.decrypt(state.ID);
          if(idDec == stateStr){
            this.formGroup.controls['statusControl'].setValue(`${state.ID}-enc`);
          }
        }
        
        this.formGroup.controls['equipmentTypeControl'].enable();
        this.formGroup.controls['equipmentModelControl'].enable();
        dialogRef.close();

        this.buildPreviewTag('', '');
      }
    }
  }

  async buildPreviewTag(controlName: string, value: string){
    this.generatedTag = "";

    let codeType = this.formGroup.controls['codeTypeControl'].value;
    let controlValues: Map<string, string> = new Map();
    let line = this.formGroup.controls['lineControl'].value;
    controlValues.set('lineControl', line);
    
    for(const control of this.codeControlsStr){
      if(!controlValues.has(control)){
        let controlValue = "";
        if(controlName == control){
          controlValue = value;
        }else{
          controlValue = this.formGroup.controls[control].value;
        }

        if(controlValue != null && controlValue != undefined && controlValue != ''){
          if(controlValue.includes('-enc')){
            controlValue = controlValue.replace('-enc', '');
            controlValue = await this._encService.decrypt(controlValue);
          }else if((control == 'originElementControl' || control == 'destinyElementControl') && codeType == '4'){
            let codeArr = controlValue.split('_');
            let lbsArr = codeArr[0].split('.').reverse();
            let pbsArr = codeArr[1].split('-').reverse();

            controlValue = lbsArr[0];
            if(control == 'originElementControl'){
              this.formGroup.controls['originSequenceControl'].setValue(pbsArr[0]);
            }else{
              this.formGroup.controls['destinySequenceControl'].setValue(pbsArr[0]);
            }
          }else if((control == 'originElementControl' || control == 'destinyElementControl') && codeType != '2'){
            controlValue = this.processElement(controlValue, 'element');
          }else if(control == 'originElementControl' && codeType == '2'){
            let valArr = controlValue.split('-').reverse();
            controlValue = valArr[0].trim();
          }else if((control == 'originKilometersControl' || control == 'destinyKilometersControl')){
            controlValue = controlValue.replace('-km', '');
            controlValue = controlValue.replace('.', ',');
          }else if(control == 'trainAreaControl'){
            let valueArr = controlValue.split('(').reverse();
            controlValue = valueArr[0].replace(')', '');
          }else if(control == 'equipmentModelControl'){
            controlValue = controlValue.replace('-', '');
          }
        }

        controlValues.set(control, controlValue);
      }
    }

    let hierarchy = this.formGroup.controls['hierarchyControl'].value;
    if(hierarchy == 'Hijo'){
      let parentCodeVal = this.formGroup.controls['fatherControl'].value;
      let parentCodeArr = parentCodeVal.split(' - ');

      this.generatedTag = parentCodeArr[0];
      let equipmentControls = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
      let equipmentTag = "";

      for(const key of equipmentControls){
        let val = controlValues.get(key);
        let codePart = 'N/D';

        if(val != null && val != undefined && val != ''){
          let type = key == 'equipmentModelControl' ? 'model' : 'element';
          codePart = this.processElement(val, type);
        }

        equipmentTag += `${codePart}-`;
      }
      
      equipmentTag = equipmentTag.substring(0, equipmentTag.length - 1);
      this.generatedTag += `.${equipmentTag}`;
    }else{
      switch(codeType){
        case "1": 
          let lbsControls = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 
          'originElementControl'];
          let lbsTag = "";
  
          for(const key of lbsControls){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsTag += `${codePart}.`;
          }
  
          lbsTag = lbsTag.substring(0, lbsTag.length - 1);
          let coords = controlValues.get('originCoordsControl');

          if(coords != null && coords != undefined && coords != ''){
            lbsTag += `+${coords}`;
          }else{
            lbsTag += `+N/D`;
          }
          
          let pbsControls = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag = "";
  
          for(const key of pbsControls){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag += `${codePart}.`;
          }
  
          pbsTag = pbsTag.substring(0, pbsTag.length - 1);
          let equipmentControls = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag = "";
  
          for(const key of equipmentControls){
            let val = controlValues.get(key)!;
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != '' && key != 'equipmentIDControl'){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }else if(key == 'equipmentIDControl'){
              codePart = val;
            }
  
            equipmentTag += `${codePart}-`;
          }
          
          equipmentTag = equipmentTag.substring(0, equipmentTag.length - 1);
          this.generatedTag = `${lbsTag}_${pbsTag}.${equipmentTag}`;
        break;
        case "2": 
          let lbsControls2 = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 
          'originElementControl', 'pccIntersectionControl', 'pccPositionControl'];
          let lbsTag1 = "";
  
          for(const key of lbsControls2){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsTag1 += `${codePart}.`;
          }
  
          lbsTag1 = lbsTag1.substring(0, lbsTag1.length - 1);
          let pbsControls1 = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag1 = "";
  
          for(const key of pbsControls1){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag1 += `${codePart}.`;
          }
  
          pbsTag1 = pbsTag1.substring(0, pbsTag1.length - 1);
          let equipmentControls1 = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag1 = "";
  
          for(const key of equipmentControls1){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }
  
            equipmentTag1 += `${codePart}-`;
          }
          
          equipmentTag1 = equipmentTag1.substring(0, equipmentTag1.length - 1);
          this.generatedTag = `${lbsTag1}_${pbsTag1}.${equipmentTag1}`;
        break;
        case "3":
          let lbsOriginControls = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 
          'originElementControl', 'originKilometersControl'];
          let lbsOriginTag = "";
  
          for(const key of lbsOriginControls){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsOriginTag += `${codePart}.`;
          }
  
          lbsOriginTag = lbsOriginTag.substring(0, lbsOriginTag.length - 1);
          let lbsDestinyControls = ['destinyLocationControl', 'destinyLevelControl', 'destinyOccupationControl', 'destinyElementControl', 
          'destinyKilometersControl'];
          let lbsDestinyTag = "";
  
          for(const key of lbsDestinyControls){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsDestinyTag += `${codePart}.`;
          }
  
          lbsDestinyTag = lbsDestinyTag.substring(0, lbsDestinyTag.length - 1);
          let pbsControls2 = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag2 = "";
  
          for(const key of pbsControls2){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag2 += `${codePart}.`;
          }
  
          pbsTag2 = pbsTag2.substring(0, pbsTag2.length - 1);
          let equipmentControls2 = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag2 = "";
  
          for(const key of equipmentControls2){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }
  
            equipmentTag2 += `${codePart}-`;
          }
          
          equipmentTag2 = equipmentTag2.substring(0, equipmentTag2.length - 1);
          this.generatedTag = `${lbsOriginTag}:${lbsDestinyTag}_${pbsTag2}.${equipmentTag2}`;
        break;
        case "4":
          let lbsOriginControls0 = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 
          'originElementControl'];
          let lbsOriginTag0 = "";
  
          for(const key of lbsOriginControls0){
            let val = controlValues.get(key);
            if(key == 'originElementControl' && val != null && val.includes('+')){
              let valArr = val!.split('+');
              val = valArr[0];
            }

            let codePart = 'N/D';
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsOriginTag0 += `${codePart}.`;
          }
  
          let lbsOriginSequence = this.formGroup.controls['originSequenceControl'].value;
          if(lbsOriginSequence != undefined  && lbsOriginSequence != null && lbsOriginSequence != ''){
            lbsOriginTag0 += lbsOriginSequence;
          }else{
            lbsOriginTag0 += 'N/D';
          }

          let lbsOriginCoords = this.formGroup.controls['originCoordsControl'].value;
          if(lbsOriginCoords != undefined  && lbsOriginCoords != null && lbsOriginCoords != ''){
            lbsOriginTag0 += `+${lbsOriginCoords}`;
          }else{
            lbsOriginTag0 += '';
          }
  
          let lbsDestinyControls0 = ['destinyLocationControl', 'destinyLevelControl', 'destinyOccupationControl', 'destinyElementControl'];
          let lbsDestinyTag0 = "";
  
          for(const key of lbsDestinyControls0){
            let val = controlValues.get(key);
            if(key == 'destinyElementControl' && val != null && val.includes('+')){
              let valArr = val!.split('+');
              val = valArr[0];
            }

            let codePart = 'N/D';
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsDestinyTag0 += `${codePart}.`;
          }
  
          let lbsDestinySequence = this.formGroup.controls['destinySequenceControl'].value;
          if(lbsDestinySequence != undefined  && lbsDestinySequence != null && lbsDestinySequence != ''){
            lbsDestinyTag0 += lbsDestinySequence;
          }else{
            lbsDestinyTag0 += 'N/D';
          }

          let lbsDestinyCoords = this.formGroup.controls['destinyCoordsControl'].value;
          if(lbsDestinyCoords != undefined  && lbsDestinyCoords != null && lbsDestinyCoords != ''){
            lbsDestinyTag0 += `+${lbsDestinyCoords}`;
          }else{
            lbsDestinyTag0 += '';
          }
          
          let pbsControls3 = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag3 = "";
  
          for(const key of pbsControls3){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag3 += `${codePart}.`;
          }
  
          pbsTag3 = pbsTag3.substring(0, pbsTag3.length - 1);
          let equipmentControls3 = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag3 = "";
  
          for(const key of equipmentControls3){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }
  
            equipmentTag3 += `${codePart}-`;
          }
          
          equipmentTag3 = equipmentTag3.substring(0, equipmentTag3.length - 1);
          this.generatedTag = `${lbsOriginTag0}:${lbsDestinyTag0}_${pbsTag3}.${equipmentTag3}`;
        break;
        case "5": 
          let lbsControls3 = ['lineControl', 'originLocationControl', 'originLevelControl', 'originOccupationControl', 
          'trainAreaControl', 'originElementControl'];
          let lbsTag3 = "";
  
          for(const key of lbsControls3){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            lbsTag3 += `${codePart}.`;
          }
  
          lbsTag3 = lbsTag3.substring(0, lbsTag3.length - 1);
          let pbsControls4 = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag4 = "";
  
          for(const key of pbsControls4){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag4 += `${codePart}.`;
          }
  
          pbsTag4 = pbsTag4.substring(0, pbsTag4.length - 1);
          let equipmentControls4 = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag4 = "";
  
          for(const key of equipmentControls4){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }
  
            equipmentTag4 += `${codePart}-`;
          }
          
          equipmentTag4 = equipmentTag4.substring(0, equipmentTag4.length - 1);
          this.generatedTag = `${lbsTag3}_${pbsTag4}.${equipmentTag4}`;
        break;
        case "6":
          let originCodeType = this.formGroup.controls['mixOriginControl'].value;
          let originCode = this.formGroup.controls['originElementControl'].value;
          let lbsOrigin = "N/D";

          if(originCodeType == '3' && originCode != null){
            let codeArr6 = originCode.split('_');
            if(codeArr6.length > 1){
              let lbsArr6 = codeArr6[0].split(':');
              if(lbsArr6.length > 1){
                let lbsOriginArr6 = lbsArr6[0].split('.').reverse();
                let lbsOriginArrFn6: string[] = [];

                for(let i = 0; i < lbsOriginArr6.length; i++){
                  if(i > 0){
                    lbsOriginArrFn6.push(lbsOriginArr6[i]);
                  }
                }
                
                let lbsOriginStr6 = lbsOriginArrFn6.reverse().join('.');
                let kilometers = 'N/D';
                let kilometersVal = this.formGroup.controls['originKilometersControl'].value;

                if(kilometersVal != null && kilometersVal != undefined && kilometersVal != ''){
                  let kilometersArr = kilometersVal.split('.');
                  kilometers = kilometersArr.join(',');
                }
                  
                lbsOrigin = `${lbsOriginStr6}.${kilometers}`;
              }
            }
          }else if(originCodeType == '4' && originCode != null){
            let codeArr6 = originCode.split('_');
            if(codeArr6.length > 1){
              let lbsArr6 = codeArr6[0].split(':');
              if(lbsArr6.length > 1){
                let lbsOriginArr6 = lbsArr6[0].split('.');
                let lbsLine6 = lbsOriginArr6[0];
                let lbsOriginArrFn6: string[] = [];

                for(let i = 0; i < lbsOriginArr6.length; i++){
                  if(lbsOriginArr6[i] != lbsLine6){
                    lbsOriginArrFn6.push(lbsOriginArr6[i]);
                  }
                }

                let lbsOriginStr6 = lbsOriginArrFn6.join('.');
                let originCodePartUsed = this.formGroup.controls['originCodePartUsed'].value;
                let originCodePartUsedStr = originCodePartUsed == 'O' ? lbsOriginStr6 : lbsArr6[1];
                  
                lbsOrigin = `${lbsLine6}.${originCodePartUsedStr}`;
              }
            }
          }else if(originCode != null){
            let codeArrO = originCode.split('_');
            if(codeArrO.length == 2){
              let lbsCodeArrO = codeArrO[0].split('+');
              let pbsSequenceO = codeArrO[1].split('-').reverse();

              if(lbsCodeArrO.length == 2){
                lbsOrigin = `${lbsCodeArrO[0]}.${pbsSequenceO[0]}+${lbsCodeArrO[1]}`;
              }else if(lbsCodeArrO.length == 1){
                lbsOrigin = `${lbsCodeArrO[0]}.${pbsSequenceO[0]}`;
              }
            }
          }else{
            lbsOrigin = "N/D";
          }

          let destinyCodeType = this.formGroup.controls['mixDestinyControl'].value;
          let detinyCode = this.formGroup.controls['destinyElementControl'].value;
          let lbsDestiny = "N/D";

          if(destinyCodeType == '3' && detinyCode != null){
            let codeArr6 = detinyCode.split('_');
            if(codeArr6.length > 1){
              let lbsArr6 = codeArr6[0].split(':');
              if(lbsArr6.length > 1){
                let lbsDestinyArr6 = lbsArr6[1].split('.').reverse();
                let lbsDestinyArrFn6: string[] = [];

                for(let i = 0; i < lbsDestinyArr6.length; i++){
                  if(i > 0){
                    lbsDestinyArrFn6.push(lbsDestinyArr6[i]);
                  }
                }
                
                let lbsDestinyStr6 = lbsDestinyArrFn6.reverse().join('.');
                let kilometers = 'N/D';
                let kilometersVal = this.formGroup.controls['destinyKilometersControl'].value;

                if(kilometersVal != null && kilometersVal != undefined && kilometersVal != ''){
                  let kilometersArr = kilometersVal.split('.');
                  kilometers = kilometersArr.join(',');
                }
                  
                lbsDestiny = `${lbsDestinyStr6}.${kilometers}`;
              }
            }
          }else if(destinyCodeType == '4' && detinyCode != null){
            let codeArr6 = detinyCode.split('_');
            if(codeArr6.length > 1){
              let lbsArr6 = codeArr6[0].split(':');
              if(lbsArr6.length > 1){
                let lbsOriginArr6 = lbsArr6[0].split('.');
                let lbsLine6 = lbsOriginArr6[0];
                let lbsOriginArrFn6: string[] = [];

                for(let i = 0; i < lbsOriginArr6.length; i++){
                  if(lbsOriginArr6[i] != lbsLine6){
                    lbsOriginArrFn6.push(lbsOriginArr6[i]);
                  }
                }

                let lbsOriginStr6 = lbsOriginArrFn6.join('.');
                let destinyCodePartUsed = this.formGroup.controls['destinyCodePartUsed'].value;
                let destinyCodePartUsedStr = destinyCodePartUsed == 'O' ? lbsOriginStr6 : lbsArr6[1];
                  
                lbsDestiny = `${destinyCodePartUsedStr}`;
              }
            }
          }else if(detinyCode != null){
            let codeArrD = detinyCode.split('_');
            if(codeArrD.length == 2){
              let lbsCodeArrD = codeArrD[0].split('+');
              let pbsSequenceD = codeArrD[1].split('-').reverse();

              if(lbsCodeArrD.length == 2){
                let lbsCodeArrFnD = lbsCodeArrD[0].split('.').reverse();
                lbsCodeArrFnD.pop();
                lbsCodeArrFnD.reverse();

                lbsCodeArrD[0] = lbsCodeArrFnD.join('.');
                lbsDestiny = `${lbsCodeArrD[0]}.${pbsSequenceD[0]}+${lbsCodeArrD[1]}`;
              }else if(lbsCodeArrD.length == 1){
                let lbsCodeArrFnD = lbsCodeArrD[0].split('.').reverse();
                lbsCodeArrFnD.pop();
                lbsCodeArrFnD.reverse();

                lbsCodeArrD[0] = lbsCodeArrFnD.join('.');
                lbsDestiny = `${lbsCodeArrD[0]}.${pbsSequenceD[0]}`;
              }
            }
          }else{
            lbsDestiny = "N/D";
          }

          let pbsControls6 = ['familyControl', 'subfamilyControl', 'statusControl'];
          let pbsTag6 = "";
  
          for(const key of pbsControls6){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              codePart = val;
            }
  
            pbsTag6 += `${codePart}.`;
          }
  
          pbsTag6 = pbsTag6.substring(0, pbsTag6.length - 1);
          let equipmentControls6 = ['equipmentTypeControl', 'equipmentModelControl', 'equipmentIDControl'];
          let equipmentTag6 = "";
  
          for(const key of equipmentControls6){
            let val = controlValues.get(key);
            let codePart = 'N/D';
  
            if(val != null && val != undefined && val != ''){
              let type = key == 'equipmentModelControl' ? 'model' : 'element';
              codePart = this.processElement(val, type);
            }
  
            equipmentTag6 += `${codePart}-`;
          }

          equipmentTag6 = equipmentTag6.substring(0, equipmentTag6.length - 1);
          this.generatedTag = `${lbsOrigin}:${lbsDestiny}_${pbsTag6}.${equipmentTag6}`;
        break;
      }
    }
  }

  processElement(value: string, type: string): string{
    //PASO 1: Conertir la cadena en mayúsculas
    value = value.toUpperCase();
    value = value.replace('_', '');
    value = value.replace('-', '');
    value = value.replace('.', '');
    value = value.replace(',', '');
    value = value.replace(':', '');
    value = value.replace('+', '');

    //PASO 2: Eliminar acentos
    let valueArr0 = value.split('');
    let validVal0 = "";
    valueArr0.forEach(char => {
      switch(char){
        case "Á": validVal0 += 'A'; break;
        case "É": validVal0 += 'E'; break;
        case "Í": validVal0 += 'I'; break;
        case "Ó": validVal0 += 'O'; break;
        case "Ú": validVal0 += 'U'; break;
        default: validVal0 += char; break;
      }
    });

    //PASO 3: Eliminar conectores
    const CONNECTORS = ['DE', 'PARA', 'Y', 'O', 'DEL', 'EL', 'LA', 'LOS', 'POR', 'EN'];
    let valueArr1 = validVal0.split(' ');
    let validVal1: string[] = [];
    valueArr1.forEach(word => {
      if(!CONNECTORS.includes(word) && word != ""){
        validVal1.push(word);
      }
    });

    //PASO 4: Obtener la longitud del arreglo de palabras válidas
    let validLength = validVal1.length;

    //PASO 5: Obtener el código del elemento según la longitud
    let validVal2 = "";
    if(validLength == 1){
      if(validVal1[0].length < 5){
        validVal2 = validVal1[0];
        for(let i = validVal1[0].length; i < 5; i++){
          validVal2 = `X${validVal2}`;
        }
      }else{
        validVal2 = validVal1[0].substring(0, 5);
      }
    }else if(validLength == 2){
      let word1 = "";
      if(validVal1[0].length < 2){
        word1 = `X${validVal1[0]}`;
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = "";
      if(validVal1[1].length < 3){
        word2 = validVal1[1];
        for(let i = validVal1[1].length; i < 3; i++){
          word2 = `X${word2}`;
        }
      }else{
        word2 = validVal1[1].substring(0, 3);
      }

      validVal2 = `${word1}${word2}`;
    }else if(validLength == 3){
      let word1 = "";
      if(validVal1[0].length < 2){
        word1 = `X${validVal1[0]}`;
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = validVal1[1].substring(0, 1);
      let word3 = "";
      if(validVal1[2].length < 2){
        word3 = `X${validVal1[2]}`;
      }else{
        word3 = validVal1[2].substring(0, 2);
      }

      validVal2 = `${word1}${word2}${word3}`;
    }else if(validLength == 4){
      let word1 = "";
      if(validVal1[0].length < 2){
        word1 = `X${validVal1[0]}`;
      }else{
        word1 = validVal1[0].substring(0, 2);
      }

      let word2 = validVal1[1].substring(0, 1);
      let word3 = validVal1[2].substring(0, 1);
      let word4 = validVal1[3].substring(0, 1);

      validVal2 = `${word1}${word2}${word3}${word4}`;
    }else if(validLength >= 5){
      let word1 = validVal1[0].substring(0, 1);
      let word2 = validVal1[1].substring(0, 1);
      let word3 = validVal1[2].substring(0, 1);
      let word4 = validVal1[3].substring(0, 1);
      let word5 = validVal1[4].substring(0, 1);

      validVal2 = `${word1}${word2}${word3}${word4}${word5}`;
    }
    
    return validVal2;
  }

  async changeCodeType(val: string){
    this.clearForm();
    
    this.formGroup.controls['originLocationControl'].enable();
    this.formGroup.controls['originLevelControl'].enable();
    this.formGroup.controls['originOccupationControl'].enable();
    this.formGroup.controls['familyControl'].enable();
    this.formGroup.controls['statusControl'].enable();
    this.formGroup.controls['equipmentModelControl'].enable();
    this.formGroup.controls['originElementControl'].enable();
    this.formGroup.controls['originCoordsControl'].enable();

    if(this.levelsArrAux.length > 0){
      let subLevels = this.levelsArr.filter(item => item.LABEL.includes('Nivel'));
      for(const subLevel of subLevels){
        let labelArr = subLevel.LABEL.split('(');
        labelArr.reverse();

        subLevel.LABEL = `Subterráneo (${labelArr[0]}`;
      }
    }
    
    this.levelsArrAux = [];
    if(!this.equipmentTypeDisabled){
      this.formGroup.controls['equipmentTypeControl'].enable();
    }

    if(val == '2'){
      this.formGroup.controls['pccPositionControl'].enable();
      this.formGroup.controls['originCoordsControl'].disable();
      //this.formGroup.controls['originElementControl'].disable();
    }else if(val == '3'){
      this.formGroup.controls['originKilometersControl'].enable();
      this.formGroup.controls['destinyLocationControl'].enable();
      this.formGroup.controls['destinyLevelControl'].enable();
      this.formGroup.controls['destinyOccupationControl'].enable();
      this.formGroup.controls['destinyElementControl'].enable();
      this.formGroup.controls['destinyKilometersControl'].enable();
      this.formGroup.controls['originCoordsControl'].disable();

      this.levelsArrAux = this.levelsArr;

      let subLevels = this.levelsArr.filter(item => item.LABEL.includes('Subterráneo'));
      for(const subLevel of subLevels){
        let labelArr = subLevel.LABEL.split('(');
        labelArr.reverse();

        let subLevelCode = labelArr[0].replace(')', '');
        let subLevelInd = parseInt(subLevelCode.replace('S', '')) - 1;
        let viaLabel = this.viaLabels[subLevelInd];
        let labelStr = `Nivel ${viaLabel} (${subLevelCode})`;

        subLevel.LABEL = labelStr;
      }
    }else if(val == '4'){
      this.formGroup.controls['originElementControl'].disable();
      this.formGroup.controls['originLocationControl'].disable();
      this.formGroup.controls['originLevelControl'].disable();
      this.formGroup.controls['originOccupationControl'].disable();
      this.formGroup.controls['originCoordsControl'].disable();
    }else if(val == '5'){
      this.formGroup.controls['originOccupationControl'].disable();
      this.formGroup.controls['originCoordsControl'].disable();

      for(const level of this.levelsArr){
        let codeDec = await this._encService.decrypt(level.CODE);
        if(codeDec == 'P00'){
          this.formGroup.controls['originLevelControl'].disable();
          this.formGroup.controls['originLevelControl'].setValue(`${level.CODE}-enc`);
        }
      }
    }else if(val == '6'){
      this.formGroup.controls['originLocationControl'].disable();
      this.formGroup.controls['originLevelControl'].disable();
      this.formGroup.controls['originOccupationControl'].disable();
      this.formGroup.controls['originElementControl'].disable();
      this.formGroup.controls['originCoordsControl'].disable();
      this.formGroup.controls['mixDestinyControl'].enable();
      this.formGroup.controls['mixOriginControl'].enable();
    }

    this.buildPreviewTag('', '');
  }

  clearForm(){
    this.codeControlsStr.forEach(control => {
      if(control != 'lineControl' && control != 'equipmentIDControl'){
        if(control == 'equipmentTypeControl' && this.equipmentTypeDisabled){
          this.formGroup.controls['equipmentTypeControl'].setValue(this.equipmentType);
          this.formGroup.controls['equipmentTypeControl'].disable();
        }else{
          this.formGroup.controls[control].setValue(null);
          this.formGroup.controls[control].disable();
        }
      }

      if(control == 'originLocationControl'){
        this.formGroup.controls['originLocationControl'].setValidators(Validators.required);
      }
    })
  }

  openCarAreaDialog(){
    let trainOccupation = this.formGroup.controls['originOccupationControl'].value;
    if(trainOccupation == undefined || trainOccupation == null || trainOccupation == ''){
      this._resourcesService.openSnackBar('Aún no ha seleccionado una ocupación.');
    }else{
      let dialogRef = this._dialog.open(LocateCarAreaComponent, {
        width: '1144px',
        maxWidth: '1144px',
        disableClose: true,
        data: {
          trainOccupation: trainOccupation
        }
      });

      dialogRef.afterClosed().subscribe(res => {
        if(res != null && res != undefined && res != ''){
          this.setCarArea(res);
        }
      });
    }
  }

  async setCarArea(areaEnc: string){
    let areaDec = await this._encService.decrypt(areaEnc);
    let areaFilt = null;
    
    for(const area of this.carAreas){
      let codeDec = await this._encService.decrypt(area.CODE);
      if(codeDec == areaDec){
        areaFilt = area;
      }
    }

    if(areaFilt == null){
      this._resourcesService.openSnackBar(`El area ${areaDec} es inválida.`);
    }else{
      this.formGroup.controls['trainAreaControl'].setValue(areaFilt.AREA);
      this.buildPreviewTag('trainAreaControl', areaDec);
    }
  }

  mixChange(type: string, value: string){
    if(type == 'mixOriginControl'){
      this.formGroup.controls['originCodePartUsed'].disable();
      this.formGroup.controls['originCodePartUsed'].setValue('O');
      this.formGroup.controls['originElementControl'].enable();
      this.formGroup.controls['originElementControl'].setValue(null);
      this.formGroup.controls['destinyKilometersControl'].disable();

      if(value == '3'){
        this.formGroup.controls['originKilometersControl'].enable();
      }

      if(value == '4'){
        this.formGroup.controls['originCodePartUsed'].enable();
      }
    }else{
      this.formGroup.controls['destinyCodePartUsed'].disable();
      this.formGroup.controls['destinyCodePartUsed'].setValue('D');
      this.formGroup.controls['destinyElementControl'].enable();
      this.formGroup.controls['destinyElementControl'].setValue(null);
      this.formGroup.controls['originKilometersControl'].disable();

      if(value == '3'){
        this.formGroup.controls['destinyKilometersControl'].enable();
      }

      if(value == '4'){
        this.formGroup.controls['destinyCodePartUsed'].enable();
      }
    }

    this.buildPreviewTag('', '');
  }

  async openEquipmentSearch(type: string){
    let generalCodeType = this.formGroup.controls['codeTypeControl'].value;
    let originElementVal = this.formGroup.controls['originElementControl'].value;
    let destinyElementVal = this.formGroup.controls['destinyElementControl'].value;
    let originElementEnc = originElementVal == undefined || originElementVal == null ? undefined : await this._encService.encrypt(originElementVal);
    let destinyElementEnc = destinyElementVal == undefined || destinyElementVal == null ? undefined : await this._encService.encrypt(destinyElementVal);

    let originCodificationType = this.formGroup.controls['mixOriginControl'].value;
    let originCodificationTypeEnc: string | null = null;
    
    if(type == 'origin' && generalCodeType == '6' && (originCodificationType == null || originCodificationType == undefined)){
      this._resourcesService.openSnackBar('Primero seleccione el tipo de codificación del origen');
      return;
    }else if(type == 'origin' && generalCodeType == '6' && originCodificationType != null && originCodificationType != undefined){
      originCodificationTypeEnc = await this._encService.encrypt(originCodificationType);
    }

    let destinyCodificationType = this.formGroup.controls['mixDestinyControl'].value;
    let destinyCodificationTypeEnc: string | null = null;
    
    if(type == 'destiny' && generalCodeType == '6' && (destinyCodificationType == null || destinyCodificationType == undefined)){
      this._resourcesService.openSnackBar('Primero seleccione el tipo de codificación del destino');
      return;
    }else if(type == 'destiny' && generalCodeType == '6' && destinyCodificationType != null && destinyCodificationType != undefined){
      destinyCodificationTypeEnc = await this._encService.encrypt(destinyCodificationType);
    }

    let dialogRef = this._dialog.open(SearchEquipmentComponent, {
      disableClose: true,
      width: '920px',
      maxWidth: '920px',
      data: {
        codeType: generalCodeType,
        originElement: originElementEnc,
        destinyElement: destinyElementEnc,
        equipmentType: type,
        originCodificationType: originCodificationTypeEnc,
        destinyCodificationType: destinyCodificationTypeEnc,
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != null && res != undefined && res != ''){
        this.asignElement(type, res);
      }
    });
  }

  async asignElement(type: string, codeEnc: string){
    let codeDec = await this._encService.decrypt(codeEnc);
    let control = type == 'origin' ? 'originElementControl' : 'destinyElementControl';
    let codeArr = codeDec.split('_');
    let lbsArr = codeArr[0].split('.');

    let control2 = type == 'origin' ? 'destinyElementControl' : 'originElementControl';
    let value2 = this.formGroup.controls[control2].value;
    
    let originLocation = type == 'origin' ? lbsArr[1] : '';
    let destinyLocation = type == 'origin' ? '' : lbsArr[1];

    let originLevel = type == 'origin' ? lbsArr[2] : '';
    let destinyLevel = type == 'origin' ? '' : lbsArr[2];

    let originOccupation = type == 'origin' ? lbsArr[3] : '';
    let destinyOccupation = type == 'origin' ? '' : lbsArr[3];

    let originCoords = type == 'origin' ? lbsArr[4] : '';
    if(originCoords.includes('+') && type == 'origin'){
      let originCoordsArr = originCoords.split('+').reverse();
      originCoords = originCoordsArr[0];

      this.formGroup.controls['originCoordsControl'].setValue(originCoords);
    }else if(type == 'origin'){
      this.formGroup.controls['originCoordsControl'].setValue('');
    }

    let destinyCoords = type == 'origin' ? '' : lbsArr[4];
    if(destinyCoords.includes('+') && type == 'destiny'){
      let destinyCoordsArr = destinyCoords.split('+').reverse();
      destinyCoords = destinyCoordsArr[0];

      this.formGroup.controls['destinyCoordsControl'].setValue(destinyCoords);
    }else if(type == 'destiny'){
      this.formGroup.controls['destinyCoordsControl'].setValue('');
    }
    

    if(value2 != null && value2 != undefined && value2 != ''){
      let valueArr2 = value2.split('_');
      let lbsArr2 = valueArr2[0].split('.');

      originLocation = type == 'origin' ? originLocation : lbsArr2[1];
      destinyLocation = type == 'origin' ? lbsArr2[1] : destinyLocation;

      originLevel = type == 'origin' ? originLevel : lbsArr2[2];
      destinyLevel = type == 'origin' ? lbsArr2[2] : destinyLevel;
      
      originOccupation = type == 'origin' ? originOccupation : lbsArr2[3];
      destinyOccupation = type == 'origin' ? lbsArr2[3] : destinyOccupation;
    }

    for(const location of this.locationsArr){
      let codeDec = await this._encService.decrypt(location.CODE);

      if(codeDec == originLocation){
        this.formGroup.controls['originLocationControl'].setValue(`${location.CODE}-enc`);
      }
      
      if(codeDec == destinyLocation){
        this.formGroup.controls['destinyLocationControl'].setValue(`${location.CODE}-enc`);
      }
    }
    
    for(const level of this.levelsArr){
      let codeDec = await this._encService.decrypt(level.CODE);

      if(codeDec == originLevel){
        this.formGroup.controls['originLevelControl'].setValue(`${level.CODE}-enc`);
      }
      
      if(codeDec == destinyLevel){
        this.formGroup.controls['destinyLevelControl'].setValue(`${level.CODE}-enc`);
      }
    }

    for(const occupation of this.occupations){
      let codeDec = await this._encService.decrypt(occupation.OCUPACION);

      if(codeDec == originOccupation){
        this.formGroup.controls['originOccupationControl'].setValue(`${occupation.OCUPACION}-enc`);
      }
      
      if(codeDec == destinyOccupation){
        this.formGroup.controls['destinyOccupationControl'].setValue(`${occupation.OCUPACION}-enc`);
      }
    }

    this.formGroup.controls[control].setValue(codeDec);
    this.buildPreviewTag(control, codeDec);
  }

  openIntersectionSelector(){
    let dialogRef = this._dialog.open(LocatePccComponent, {
      width: '720px',
      maxWidth: '720px',
      disableClose: true,
    });

    dialogRef.afterClosed().subscribe(res =>{
      if(res != undefined && res != null && res != ''){
        this.setElement(res);
      }
    });
  }

  async setElement(dataEnc: string){
    let dataDec = await this._encService.decrypt(dataEnc);
    this.formGroup.controls['pccIntersectionControl'].setValue(dataDec);
    
    this.buildPreviewTag('', '');
  }

  pccPositionChange(value: string, action: string){
    let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    let valueArr = value.split('');
    let validVal = "";

    valueArr.forEach(char => {
      if(numbers.includes(char)){
        validVal += char;
      }
    });

    if(action == 'blur' && validVal.length < 2){
      validVal = `0${validVal}`;
    }

    this.formGroup.controls['pccPositionControl'].setValue(validVal);
    this.formGroup.controls['pccPositionControl'].markAsTouched();
    
    this.buildPreviewTag('pccPositionControl', validVal);
  }

  kilometersChange(value: string, formControl: string, isMixed: boolean = false, actionType: string = 'input'){
    let numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.'];
    let valueArr = value.split('');
    let validVal = "";

    valueArr.forEach(char => {
      if(numbers.includes(char)){
        if(char != '.'){
          validVal += char;
        }else if(!validVal.includes('.')){
          validVal += char;
        }
      }
    });

    if(isMixed && actionType == 'blur'){
      let selectedCode = formControl.includes('origin') ? this.formGroup.controls['originElementControl'].value : this.formGroup.controls['destinyElementControl'].value;
      if(selectedCode != null && selectedCode != undefined && selectedCode != ''){
        let selectedCodeArr = selectedCode.split('_');
        if(selectedCodeArr.length > 1){
          let lbsArr = selectedCodeArr[0].split(':');
          if(lbsArr.length > 1){
            let selectedCodeOriginArr = lbsArr[0].split('.').reverse();
            let selectedCodeDestinyArr = lbsArr[1].split('.').reverse();
            let originKilometerStr = selectedCodeOriginArr[0].replace(',', '.');
            let destinyKilometerStr = selectedCodeDestinyArr[0].replace(',', '.');
            let originKilometerNum = parseFloat(originKilometerStr);
            let destinyKilometerNum = parseFloat(destinyKilometerStr);

            if(!isNaN(originKilometerNum) && !isNaN(destinyKilometerNum)){
              let validValNum = parseFloat(validVal);
              let kilometerLabel = formControl.includes('origin') ? 'origen' : 'destino';
              if(validValNum > originKilometerNum){
                this._resourcesService.openSnackBar(`El kilómetro de ${kilometerLabel} es mayor al kilómetro de origen del código seleccionado.`);
                this.formGroup.controls[formControl].setValue('');
                this.buildPreviewTag(formControl, '-km');
              }else if(validValNum < destinyKilometerNum){
                this._resourcesService.openSnackBar(`El kilómetro de ${kilometerLabel} es menor al kilómetro de destino del código seleccionado.`);
                this.formGroup.controls[formControl].setValue('');
                this.buildPreviewTag(formControl, '-km');
              }else{
                this.formGroup.controls[formControl].setValue(validVal);
                this.buildPreviewTag(formControl, `${validVal}-km`);
              }
            }
          }
        }
      }
    }else{
      this.formGroup.controls[formControl].setValue(validVal);
      this.buildPreviewTag(formControl, `${validVal}-km`);
    }
  }

  async searchSubfamilies(value: string){
    try{
      this.searchingSubfamilies = true;
      let familyCode = value.replace('-enc', '');

      let idUser = localStorage.getItem('idusuario')!;
      let subfamilies: SubfamiliesListResponse = await lastValueFrom(this._equipmentManagementService.subfamilyConsult(familyCode, idUser, 1));

      if(subfamilies.error){
        this._resourcesService.openSnackBar(subfamilies.msg);
        this.formGroup.controls['subfamilyControl'].disable();
      }else{
        this.subfamiliesArr = [];
        this.formGroup.controls['subfamilyControl'].enable();

        let subfamiliesTmp: SubfamiliesListItem[] = [];
        for(const subfamily of subfamilies.response){
          let codeDec = await this._encService.decrypt(subfamily.CODIGOSUBFAMILIA);

          subfamily.NOMBRESUBFAMILIA = `${subfamily.NOMBRESUBFAMILIA} (${codeDec})`;
          if(subfamily.ESTADO == 'Activo'){
            subfamiliesTmp.push(subfamily);
          }
        }

        this.subfamiliesArr = subfamiliesTmp;
      }

      this.formGroup.controls['subfamilyControl'].setValue(null);
      this.searchingSubfamilies = false;
      this.buildPreviewTag('familyControl', value);
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (13).');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (14).');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }

  checkFile(event: any, type: string){
    let extArr = event.target.files[0].name.split(".").reverse();
    let extStr = extArr[0].toLowerCase();

    if(type == 'imagen'){
      let allowedImages = ['png', 'gif', 'jpg'];
      if(!allowedImages.includes(extStr)){
        this._resourcesService.openSnackBar(`La extensión ${extStr} no corresponde a una imagen.`);
        return;
      }
    }else if(type == 'documento'){
      let allowedImages = ['pdf', 'doc', 'docx', 'ppt', 'pptx'];
      if(!allowedImages.includes(extStr)){
        this._resourcesService.openSnackBar(`La extensión ${extStr} no corresponde a una imagen.`);
        return;
      }
    }else{
      return;
    }
    
    let fileTypes = availableFiles;
    let sizes = Object.keys(fileTypes);
    let extensions = Object.values(fileTypes);
    let maxSizeMB = 0;

    let i = 0;
    extensions.forEach(ext => {
      let size = parseInt(sizes[i]);

      if(ext.includes(extStr)) maxSizeMB = size;
      i++;
    });

    if(maxSizeMB == 0){
      this._resourcesService.openSnackBar(`Los archivos ${extStr} no están soportados`);
    }else{
      let maxFileSize = 1048576 * maxSizeMB;
      let fileSize = event.target.files[0].size;

      if(fileSize > maxFileSize){
        this._resourcesService.openSnackBar(`El tamaño del archivo supera el límite de ${maxSizeMB} MB`);
      }else{
        let alreadyAttached = false;
        this.attachedImages.forEach(file => {
          alreadyAttached = file.name == event.target.files[0].name && file.size == this._resourcesService.formatBytes(event.target.files[0].size);
        });

        if(alreadyAttached){
          this._resourcesService.openSnackBar("El archivo seleccionado ya fue adjuntado.");
        }else{
          if(type == 'imagen'){
            this.uploadingImages = true;
          }else if(type == 'documento'){
            this.uploadingDocuments = true;
          }
          
          this.disableAttachActions = true;
          this.uploadTmp(event.target.files[0], type);
        }
      }
    }
  }

  async uploadTmp(fileData: any, type: string){
    try{
      let idUser = localStorage.getItem('idusuario');
      let formData = new FormData();

      formData.append('file', fileData);
      formData.append('id_user', idUser!);
      formData.append('linea', "1");

      let response = await lastValueFrom(this._gdelService.uploadTempFile(formData));

      if(response.error){
        this._resourcesService.openSnackBar(response.msg);
      }else{
        let uploadedFile: TempFileInfo = {
          id: response.response.idArchivo,
          name: fileData.name,
          size: this._resourcesService.formatBytes(fileData.size),
          type: 'Nuevo',
        };

        if(type == 'imagen'){
          this.attachedImages.push(uploadedFile);
          this.imagesDataSource = new MatTableDataSource(this.attachedImages);
          this.uploadingImages = false;
        }else{
          this.attachedDocuments.push(uploadedFile);
          this.documentsDataSource = new MatTableDataSource(this.attachedDocuments);
          this.uploadingDocuments = false;
        }
      }

      this.disableAttachActions = false;
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (15).');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (16).');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.uploadingImages = false;
      this.uploadingDocuments = false;
      this.disableAttachActions = false;
    }
  }

  async deleteFile(idFile: string, type: string){
    try{
      this.disableAttachActions = true;
      let idUser = localStorage.getItem('idusuario');
  
      await lastValueFrom(this._gdelService.deleteTempFile({
        'id_user': idUser!,
        'id_file': idFile,
        'linea': 1,
      }));
  
      let attachedAux: TempFileInfo[] = [];
      if(type == 'imagen'){
        this.attachedImages.forEach(item => {
          if(item.id != idFile){
            attachedAux.push(item);
          }
        });

        this.attachedImages = attachedAux;
        this.imagesDataSource = new MatTableDataSource(this.attachedImages);
      }else{
        this.attachedDocuments.forEach(item => {
          if(item.id != idFile){
            attachedAux.push(item);
          }
        });

        this.attachedDocuments = attachedAux;
        this.documentsDataSource = new MatTableDataSource(this.attachedDocuments);
      }

      this.disableAttachActions = false;
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (17).');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (18).');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.disableAttachActions = false;
    }
  }

  async saveEquipment(){
    try{
      if(this.formGroup.invalid){
        this._resourcesService.openSnackBar('Por favor ingrese la información requerida.');
      }else if(this.attachedImages.length < 1){
        this._resourcesService.openSnackBar('La galería de imágenes debe contener por lo menos 1 registro.');
      }else if(this.attachedDocuments.length < 1){
        this._resourcesService.openSnackBar('Los documentos relacionados deben contener por lo menos 1 registro.');
      }else{
        this._resourcesService.openSnackBar('Guardando registro...');
        let formValue = this.formGroup.getRawValue();
        let formData = new FormData();
        let idUser = localStorage.getItem('idusuario')!;
  
        formData.append('id_user', idUser);
        formData.append('linea', '1');
        formData.append('hierarchy', formValue.hierarchyControl);
  
        if(formValue.hierarchyControl == 'Hijo'){
          let parentArr = formValue.fatherControl.split(' - ');
          let parentEnc = await this._encService.encrypt(parentArr[0]);

          formData.append('parent_equipment', parentEnc);
        }
  
        let originLocation = formValue.originLocationControl.replace('-enc', '');
        let originLevel = formValue.originLevelControl.replace('-enc', '');
        let originOccupation = formValue.originOccupationControl.replace('-enc', '');
        let family = formValue.familyControl.replace('-enc', '');
        let subfamily = formValue.subfamilyControl.replace('-enc', '');
        let status = formValue.statusControl.replace('-enc', '');
  
        formData.append('code_type', formValue.codeTypeControl);
        if(formValue.codeTypeControl == '1'){
          formData.append('origin_occupation', originOccupation);
          formData.append('origin_element', formValue.originElementControl);
          formData.append('origin_coords', formValue.originCoordsControl);
        }else if(formValue.codeTypeControl == '2'){
          formData.append('origin_occupation', originOccupation);
          formData.append('origin_element', formValue.originElementControl);
          formData.append('origin_coords', 'XXXXXXX');

          formData.append('pcc_intersection', formValue.pccIntersectionControl);
          formData.append('pcc_position', formValue.pccPositionControl);
        }else if(formValue.codeTypeControl == '3'){
          formData.append('origin_occupation', originOccupation);
          formData.append('origin_element', formValue.originElementControl);
          formData.append('origin_coords', 'XXXXXXX');

          let destinyLocation = formValue.destinyLocationControl.replace('-enc', '');
          let destinyLevel = formValue.destinyLevelControl.replace('-enc', '');
          let destinyOccupation = formValue.destinyOccupationControl.replace('-enc', '');

          formData.append('origin_kilometer', formValue.originKilometersControl);
          formData.append('destiny_location', destinyLocation);
          formData.append('destiny_level', destinyLevel);
          formData.append('destiny_occupation', destinyOccupation);
          formData.append('destiny_element', formValue.destinyElementControl);
          formData.append('destiny_kilometer', formValue.destinyKilometersControl);
        }else if(formValue.codeTypeControl == '4'){
          formData.append('origin_occupation', originOccupation);

          let originElementEnc = await this._encService.encrypt(formValue.originElementControl);
          formData.append('origin_element_enc', originElementEnc);
          formData.append('origin_coords', formValue.originCoordsControl);

          let destinyElementEnc = await this._encService.encrypt(formValue.destinyElementControl);
          let destinyLocation = formValue.destinyLocationControl.replace('-enc', '');
          let destinyLevel = formValue.destinyLevelControl.replace('-enc', '');
          let destinyOccupation = formValue.destinyOccupationControl.replace('-enc', '');

          formData.append('destiny_element_enc', destinyElementEnc);
          formData.append('destiny_location', destinyLocation);
          formData.append('destiny_level', destinyLevel);
          formData.append('destiny_occupation', destinyOccupation);
          formData.append('destiny_coords', formValue.destinyCoordsControl);
        }else if(formValue.codeTypeControl == '5'){
          let originOccupationEnc = await this._encService.encrypt(originOccupation);
          formData.append('origin_occupation', originOccupationEnc);
          
          let originElement = formValue.originElementControl.replace('-enc', '');
          formData.append('origin_element', originElement);
          formData.append('origin_coords', 'XXXXXXX');

          let trainAreaArr = formValue.trainAreaControl.split('(').reverse();
          let trainAreaStr = trainAreaArr[0].replace(')', '');
          let trainAreaEnc = await this._encService.encrypt(trainAreaStr);
          formData.append('train_area', trainAreaEnc);
        }else if(formValue.codeTypeControl == '6'){
          formData.append('origin_occupation', originOccupation);
          formData.append('origin_code_type', formValue.mixOriginControl);
          if(formValue.originCoordsControl == null || formValue.originCoordsControl == undefined || formValue.originCoordsControl == ''){
            formData.append('origin_coords', 'XXXXXXX');
          }else{
            formData.append('origin_coords', formValue.originCoordsControl);
          }

          if(formValue.mixOriginControl == '4'){
            formData.append('origin_code_part_used', formValue.originCodePartUsed);
          }
          
          formData.append('destiny_code_type', formValue.mixDestinyControl);
          if(formValue.destinyCoordsControl == null || formValue.destinyCoordsControl == undefined || formValue.destinyCoordsControl == ''){
            formData.append('destiny_coords', 'XXXXXXX');
          }else{
            formData.append('destiny_coords', formValue.destinyCoordsControl);
          }

          if(formValue.mixDestinyControl == '4'){
            formData.append('destiny_code_part_used', formValue.destinyCodePartUsed);
          }

          let originElementEnc = await this._encService.encrypt(formValue.originElementControl);
          formData.append('origin_element', originElementEnc);

          let destinyElementEnc = await this._encService.encrypt(formValue.destinyElementControl);
          formData.append('destiny_element', destinyElementEnc);
        }

        formData.append('origin_location', originLocation);
        formData.append('origin_level', originLevel);
        formData.append('family', family);
        formData.append('subfamily', subfamily);
        formData.append('status', status);
        formData.append('equipment_type', formValue.equipmentTypeControl);
        formData.append('equipment_model', formValue.equipmentModelControl);
        formData.append('origin_coords_plane', formValue.originCoordsPlaneControl);

        let additionalCodesStr = JSON.stringify(this.additionalCodes);
        let additionalCodesEnc = await this._encService.encrypt(additionalCodesStr);
        formData.append('additional_codes', additionalCodesEnc);
  
        let imagesArr = JSON.stringify(this.attachedImages);
        let documentsArr = JSON.stringify(this.attachedDocuments);
        let equipmentCodeEnc = await this._encService.encrypt(this.generatedTag);
        let serialNumberEnc = await this._encService.encrypt(formValue.serialNumberControl);
  
        formData.append('images', imagesArr);
        formData.append('documents', documentsArr);
  
        let acquisitionDateObj = formValue.acquisitionDateControl as Date;
        let acquisitionDateStr = `${acquisitionDateObj.getFullYear()}-${acquisitionDateObj.getMonth() + 1}-${acquisitionDateObj.getDate()}`;
  
        let warrantyStartDateObj = formValue.warrantyStartDateControl as Date;
        let warrantyStartDateStr = `${warrantyStartDateObj.getFullYear()}-${warrantyStartDateObj.getMonth() + 1}-${warrantyStartDateObj.getDate()}`;
  
        let warrantyEndDateObj = formValue.warrantyEndDateControl as Date;
        let warrantyEndDateStr = `${warrantyEndDateObj.getFullYear()}-${warrantyEndDateObj.getMonth() + 1}-${warrantyEndDateObj.getDate()}`;
        
        formData.append('acquisition_date', acquisitionDateStr);
        formData.append('warranty_start_date', warrantyStartDateStr);
        formData.append('warranty_end_date', warrantyEndDateStr);

        let providerArr = formValue.equipmentProviderControl.split(')');
        let providerStr = providerArr[0].replace('(', '');
        let providerEnc = await this._encService.encrypt(providerStr);
        
        formData.append('equipment_provider', providerEnc);
        formData.append('serial_number', serialNumberEnc);
        formData.append('has_software', formValue.hasSoftwareControl);
  
        if(formValue.hasSoftwareControl == 'Si'){
          formData.append('software_name', formValue.softwareNameControl);
          formData.append('software_version', formValue.softwareVersionControl);
        }
  
        formData.append('pre_generated_code', equipmentCodeEnc);

        await lastValueFrom(this._equipmentManagementService.equipmentPreCodification(formData));
        this._resourcesService.openSnackBar('El registro del equipamiento fue enviado para su revisión correctamente.');

        this.goBack(1);
      }
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (19).');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (20).');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }

  openCarDialog(){
    let dialogRef = this._dialog.open(LocateCarComponent, {
      width: '945px',
      maxWidth: '945px',
      disableClose: true,
      data: {
        trainOccupations: this.trainOccupations,
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != undefined && res != null && res != ''){
        let resArr = res.split('(').reverse();
        let car = resArr[0].replace(')', '');

        this.formGroup.controls['trainAreaControl'].setValue(null);
        this.formGroup.controls['originOccupationControl'].setValue(car);
        this.buildPreviewTag('originOccupationControl', car);
        this.searchCarAreas(car);
      }
    })
  }

  async searchCarAreas(trainOccupation: string){
    try{
      this.searchingCarAreas = true;

      let idUser =localStorage.getItem('idusuario')!;
      let trainOccupationEnc = await this._encService.encrypt(trainOccupation);
      let carAreas: CarAreasListResponse = await lastValueFrom(this._equipmentManagementService.occupationTrainAreaConsult(
        trainOccupationEnc,
        idUser,
        1
      ));

      if(carAreas.error){
        this._resourcesService.openSnackBar(carAreas.msg);
      }else{
        let carAreasArr: CarAreasListItem[] = [];
        for(const area of carAreas.response){
          let codeDec = await this._encService.decrypt(area.CODE);
          let areaDec = await this._encService.decrypt(area.AREA);

          area.AREA = `${areaDec} (${codeDec})`;
          carAreasArr.push(area);
        }

        this.carAreas = carAreasArr;
      }

      this.searchingCarAreas = false;
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (21).');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado (22).');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }

      this.searchingCarAreas = false;
    }
  }

  openArborescenceSearch(){
    let dialogRef = this._dialog.open(GraphicEquipmentSearchComponent, {
      disableClose: true,
      width: '720px',
      maxWidth: '720px',
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != null && res != undefined && res != ''){
        this.formGroup.controls['fatherControl'].setValue(res);
        
        //this.changeEquipmentTable(res);
      }
    });
  }

  searchCoords(coordsType: string){
    this.coordsType = coordsType;
    this.locatingCoords = true;
  }

  async setCoords(event: any){
    if(event != null && event != undefined && event != ''){
      let coordsControl = `${this.coordsType}Control`;
      let coordsPlaneControl = `${this.coordsType}PlaneControl`;
      let dataObj = JSON.parse(event);
      let idPlaneEnc = await this._encService.encrypt(dataObj.idPlane);

      if(this.formGroup.contains(coordsControl)){
        this.formGroup.controls[coordsControl].setValue(dataObj.coords);
        this.formGroup.controls[coordsPlaneControl].setValue(idPlaneEnc);
        this.buildPreviewTag(coordsControl, dataObj.coords);
      }
    }
    
    this.coordsType = '';
    this.locatingCoords = false;
  }

  addAdditionalCode(){
    this.additionalCodes.push('');
  }

  removeAdditionalCode(index: number){
    let additionalCodesAux: string[] = [];

    for(let i = 0; i < this.additionalCodes.length; i++){
      if(i != index){
        additionalCodesAux.push(this.additionalCodes[i]);
      }
    }

    this.additionalCodes = additionalCodesAux;
  }

  additionalCodeChange(additionalCode: string, index: number){
    this.additionalCodes[index] = additionalCode;
  }
}
