import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { MenuModules, NestedMenuInterface } from '../../interfaces/nested-menu.interface';
import { NavItem } from '../../interfaces/nav-item.interface';
import { NotificationDetailsResponse, NotificationsListItem, NotificationsListResponse } from '../../interfaces/notification.interface';
import { MatSidenav } from '@angular/material/sidenav';
import { DOCUMENT } from '@angular/common';
import { ResourcesService } from '../../services/resources.service';
import { Router } from '@angular/router';
import { LoginDataService } from '../../services/login-data.service';
import { EncService } from '../../services/enc.service';
import { SocketService } from '../../services/socket.service';
import { UsersProfilesService } from '../../services/users-profiles.service';
import { MatDialog } from '@angular/material/dialog';
import { ModulesService } from '../../services/modules.service';
import { AdvicesService } from '../../services/advices.service';
import { SystemAdminService } from '../../services/system-admin.service';
import { CataloguesService } from '../../services/catalogues.service';
import { EquipmentManagementService } from '../../services/equipment-management.service';
import { NotificationsService } from '../../services/notifications.service';
import { FunctionsService } from '../../services/functions.service';
import { CorrectiveMaintenanceService } from '../../services/corrective-maintenance.service';
import { AlertComponent } from '../resources/dialogs/alert/alert.component';
import { lastValueFrom } from 'rxjs';
import { MaintenanceStatusResponse } from '../../interfaces/maintenance-status.interface';
import { Permissions } from '../../interfaces/permissions.interface';
import { ProfileInterface } from '../../interfaces/profile.interface';
import { Advice, AdviceResponse } from '../../interfaces/advice.interface';
import { AdviceAlertComponent } from './advice-alert/advice-alert.component';
import { InitialDataUploadComponent } from '../initial-data-upload/initial-data-upload.component';
import { BasicAlertComponent } from '../resources/dialogs/basic-alert/basic-alert.component';
import { PermissionsData } from '../acquisition-management/acquisition-management.component';
import { TypeFormSubcontract } from '../../interfaces/personal-managment/subcontractist.interface';
import { TypeForm } from '../../interfaces/acquisition-management/provider.interface';
import { EquipmentDetailsResponse } from '../../interfaces/equipment-management.interface';
import { CorrectiveWorkOrderDetailsResponse } from '../../interfaces/corrective-maintenance.interface';
import { EquipmentAlertComponent } from './equipment-alert/equipment-alert.component';
import { ActiveSessionsNumberResponse } from '../../interfaces/active-sessions-number.interface';
import { CatalogueCoins, CatalogueCoinsDocument, ResponseDataCatalogueCoins } from '../../interfaces/catalogue.interface';
import { MyProfileComponent } from './my-profile/my-profile.component';
import { NotificationDialogComponent } from './notification-dialog/notification-dialog.component';
import { GdelService } from '../../services/gdel.service';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';

@Component({
    selector: 'app-template',
    templateUrl: './template.component.html',
    styleUrl: './template.component.css',
    standalone: false
})
export class TemplateComponent implements OnInit {
  nestedMenu: MenuModules[];
  navItems: NavItem[];
  menuItems: MenuModules[];

  showFiller = false;
  panelOpenState = false;
  screen_small = false;

  maintenanceActivated = false;
  maintenanceMode = false;
  isLoading = true;
  minutesLeft = 5;
  secondsLeft = 0;
  errorsCont = 0;
  timeLeft = "5:00";
  enabledSessions: number;
  usedSessions: number;

  userName = "";

  // public title:string = 'Sistema de Ayuda al Manteniemiento L1';
  public title:string = 'Sistema de Ayuda al Mantenimiento L1'.toUpperCase();

  modulesActivated = false;
  notificationsForPanel: NotificationsListItem[];
  unreadNotifications: number;
  totalNotifications: NotificationsListItem[];

  @ViewChild('rightDrawer') sidenav?: MatSidenav;

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _resourcesService: ResourcesService,
    private _router: Router,
    private _loginDataService: LoginDataService,
    private _encService: EncService,
    private _socketService: SocketService,
    private _profilesService: UsersProfilesService,
    private _dialog: MatDialog,
    private _modulesService: ModulesService,
    private _advicesService: AdvicesService,
    private _cataloguesService: CataloguesService,
    private _equipmentManagementService: EquipmentManagementService,
    private _notificationsService: NotificationsService,
    private _functionsService: FunctionsService,
    private _correctiveMaintenanceService: CorrectiveMaintenanceService,
    private _systemAdminService: SystemAdminService,
    private _gdelService: GdelService,
    private _matIconRegistry: MatIconRegistry,
    private _domSanitizer: DomSanitizer,
  ) {
    this.navItems = [];
    this.menuItems = [];
    this.nestedMenu = [];
    this.notificationsForPanel = [];
    this.unreadNotifications = 0;
    this.totalNotifications = [];
    this.enabledSessions = 0;
    this.usedSessions = 0;
  }

  ngOnInit(): void {
    this.isLoading = true;
    this.init();
  }

  async init(){
    try{
      //Ejecutar el tamaño de la pantalla inicial
      this.onResize();
      //Consultar el estado del modo mantenimiento
      let idUser = localStorage.getItem('idusuario');
      let maintenanceStatus: MaintenanceStatusResponse = await lastValueFrom(this._systemAdminService.getMaintenanceStatus(idUser!, 1));
      this.maintenanceMode = maintenanceStatus.response.activated;
      
      //Obtención del menú de módulos, submódulos, funciones y pantallas del SAM
      let menu: NestedMenuInterface = await lastValueFrom(this._modulesService.getMenu(idUser!, 1));
      
      //Lectura, decodificación y procesamiento de los permisos del usuario
      let permissions = localStorage.getItem('permisos');
      let permStr = await this._encService.decrypt(permissions!);
      let permObj: Permissions = JSON.parse(permStr);
      for(const item of menu.response){
        let idMod = await this._encService.decrypt(item.ID_MODULO);
        let modPerm = permObj.permissions.filter(item2 => item2.id == idMod);

        if(modPerm.length > 0){
          let access = modPerm[0].access;

          if(access > 0){
            let customIconEnc = await this._encService.isEncrypted(item.ICONO_PERSONALIZADO);
            let customIcon = customIconEnc ? await this._encService.decrypt(item.ICONO_PERSONALIZADO) : item.ICONO_PERSONALIZADO;
            item.ICONO_PERSONALIZADO = customIcon;

            if(customIcon == 'S'){
              let customIconFileURL = await lastValueFrom(this._gdelService.getPublicDocumentUrl(
                item.ARCHIVO_ICONO_PERSONALIZADO!,
                idUser!,
                1
              ));

              item.ARCHIVO_ICONO_PERSONALIZADO_URL = customIconFileURL.response.public_uri;
              this._matIconRegistry.addSvgIcon(
                item.ICONO_MODULO,
                this._domSanitizer.bypassSecurityTrustResourceUrl(customIconFileURL.response.public_uri)
              );
            }
            
            item.ID_MODULO_DEC = idMod;
            this.menuItems.push(item);


          }
        }
      }
      
      //Conexiones a los eventos del Socket
      if (window.innerWidth <= 616) {
        this.screen_small = false;
      }else if(window.innerWidth > 616){
        this.screen_small = true;
      }
  
      this._socketService.refreshPermissions().subscribe(async (profUpdEnc) => {
        try{
          let currentProfile = localStorage.getItem('perfil')!;
          let currentProfileDec = await this._encService.decrypt(currentProfile);
          let profileUpdated = await this._encService.decrypt(`${profUpdEnc}`);
  
          if(currentProfileDec == profileUpdated){
            let idUser = localStorage.getItem('idusuario')!;
            let profInfo: ProfileInterface = await lastValueFrom(this._profilesService.getProfile(
              currentProfile,
              idUser,
              1
            ));
    
            for(const item of profInfo.response.PERMISOS.permissions){
              item.id = await this._encService.decrypt(item.id);
            }

            let newPermArr = await this._functionsService.processPermissions(profInfo.response.PERMISOS.permissions);
            let newPermObj: Permissions = {permissions: newPermArr};
            
            let oldPerm = await this._encService.decrypt(localStorage.getItem('permisos')!);
            let newPerm = JSON.stringify(newPermObj);
  
            if(oldPerm != newPerm){
              let permiEnc = await this._encService.encrypt(newPerm);
              localStorage.setItem('permisos', permiEnc);
              this.menuItems = [];
  
              for(const item of this.nestedMenu){
                let idMod = item.ID_MODULO_DEC;
                let modPerm = profInfo.response.PERMISOS.permissions.filter(item2 => item2.id == idMod);

                if(modPerm.length > 0){
                  let access = modPerm[0].access;
                  if(access > 0){
                    this.menuItems.push(item);
                  }
                }
              }
  
              this._resourcesService.openSnackBar('Sus permisos fueron actualizados.');
            }
          }
        }catch(error: any){
          if(error.error == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (1).');
          }else if(error.error.msg == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (2).');
          }else{
            this._resourcesService.openSnackBar(error.error.msg);
          }
        }
      });
  
      this._socketService.advicePublished().subscribe(async (adviceID) => {
        let idUser = localStorage.getItem('idusuario')!;
        let advice: AdviceResponse = await lastValueFrom(this._advicesService.getAdvice(`${adviceID}`, idUser, 1));
        let userPublish = '';

        if(advice.response.USRMOD != null){
          let usrModArr = advice.response.USRMOD.split('(').reverse();
          userPublish = usrModArr[0].replace(')', '');
        }else{
          let usrRegArr = advice.response.USRREG.split('(').reverse();
          userPublish = usrRegArr[0].replace(')', '');
        }

        let idUserDec = await this._encService.decrypt(idUser);
        if(userPublish != idUserDec){
          let audArr = JSON.parse(advice.response.AUDIENCIA);
          let profiles: string[] = [];
          let users: string[] = [];

          for(const item of audArr){
            let idDec = await this._encService.decrypt(item.id);
            if(item.type == 'user'){
              users.push(idDec);
            }else{
              profiles.push(idDec);
            }
          }
  
          let perfEnc = localStorage.getItem('perfil');
          let perfDec = await this._encService.decrypt(perfEnc!);
  
          if(profiles.includes(perfDec) || users.includes(idUserDec)){
            this.openAdviceAlert(advice.response);
          }
        }
      });

      this._socketService.showTimerAlert().subscribe((_) => {
        this._dialog.open(BasicAlertComponent, {
          data: {
            title: 'Modo mantenimiento activado',
            body: 'El modo mantenimiento fue activado por un administrador, el sistema entrará en este modo en 5 minutos, por lo tanto deberá guardar sus cambios y cerrar sesión antes de terminar el tiempo.'
          }
        });

        this.maintenanceActivated = true;
      });

      this._socketService.timerUpdated().subscribe((time) => {
        this.timeLeft = time;
      });
  
      this._socketService.closeSessions().subscribe((_) => {
        setTimeout(() => {
          this.timeLeft = `00:00`;
          this.logout();
        }, 1000);
      });

      this._socketService.getNewProvider().subscribe(async (idProvider) => {
        if (idProvider === null || idProvider === undefined || idProvider === '') {
          this._resourcesService.openSnackBar(`ERR_GLB003: Ocurrió un error al obtener el ID del provedor.`);
          return; 
        }

        const encPermisos = localStorage.getItem('permisos');
        if (encPermisos === undefined || encPermisos === null || encPermisos === '') {
          return ;
        }
        
        const strPermisos:string = await this._encService.decrypt(encPermisos);
        const arrPermisos = JSON.parse(strPermisos);

        arrPermisos.permissions.map(async (permissionModule:PermissionsData) => {
          if (permissionModule.id === 'S002V01M11GPRS' && permissionModule.access > 0) {

            permissionModule.children.map(async (permissionSubmodule:PermissionsData) => {
              if (permissionSubmodule.id === 'S002V01S01GESU' && permissionSubmodule.access > 0) {

                permissionSubmodule.children.map(async (permissionFunction:PermissionsData) => {
                  if (permissionFunction.id === 'S002V01F01GESU' && permissionFunction.access > 0) {

                    permissionFunction.children.map(async (permissionPantalla:PermissionsData) => {
                      if (permissionPantalla.id === 'S002V01P02RESU' && permissionPantalla.access === 2) {
                        this._dialog.open(AlertComponent, {
                          width: '500px',
                          maxWidth: '500px',
                          data: {
                            icon: 'warning',
                            title: `Registro Nuevo`,
                            description: `Se ha registrado un nuevo proveedor en el Módulo de Adquisiciones ¿Desea registrar el proveedor como un subcontratista en este momento?`
                          }
                        }).afterClosed().subscribe(async (result) => {
                          if (result) {
                            
                            const typeFormSubcontract: TypeFormSubcontract = {
                              type: 'REG',
                              idSubcontract: null,
                              idProvider: `${idProvider.toString()}`,
                            }
                      
                            const strFormSubcontract:string = JSON.stringify(typeFormSubcontract);
                            const encFormSubcontract: string = await this._encService.encrypt(strFormSubcontract);

                            this._router.navigate([`/sam/GPRS/GESU/GESU/subcontratist/form/${encFormSubcontract}`]);
                          }
                        });
                      }
                    });
                  }
                });
              }
            });
          }
        });
      });

      this._socketService.getNotice().subscribe(async (msg) => {

        if (msg === null || msg === undefined || msg === '') {
          this._resourcesService.openSnackBar(`ERR_GLB004: Ocurrió un error al obtener el mensaje.`);
          return; 
        }

        const encPermisos = localStorage.getItem('permisos');
        if (encPermisos === undefined || encPermisos === null || encPermisos === '') {
          return ;
        }
        const strPermisos:string = await this._encService.decrypt(encPermisos);
        const arrPermisos = JSON.parse(strPermisos);
        arrPermisos.permissions.map(async (permissionModule:PermissionsData) => {
          if (permissionModule.id === 'S002V01M11GPRS' && permissionModule.access > 0) {

            permissionModule.children.map(async (permissionSubmodule:PermissionsData) => {
              if (permissionSubmodule.id === 'S002V01S01GESU' && permissionSubmodule.access > 0) {

                permissionSubmodule.children.map(async (permissionFunction:PermissionsData) => {
                  if (permissionFunction.id === 'S002V01F01GESU' && permissionFunction.access > 0) {

                    permissionFunction.children.map(async (permissionPantalla:PermissionsData) => {
                      if (permissionPantalla.id === 'S002V01P02RESU' && permissionPantalla.access === 2) {
                        this._resourcesService.openSnackBar(`${msg}`);
                      }
                    });
                  }
                });
              }
            });
          }
        });

        
      });

      this._socketService.getNewSubcontract().subscribe(async (idSubcontract) => {
        
        if (idSubcontract === null || idSubcontract === undefined || idSubcontract === '') {
          this._resourcesService.openSnackBar(`Ocurrió un error al obtener el ID del provedor.`);
          return; 
        }

        const encPermisos = localStorage.getItem('permisos');
        if (encPermisos === undefined || encPermisos === null || encPermisos === '') {
          return ;
        }
        const strPermisos:string = await this._encService.decrypt(encPermisos);
        const arrPermisos = JSON.parse(strPermisos);

        arrPermisos.permissions.map(async (permissionModule:PermissionsData) => {
          if (permissionModule.id === 'S002V01M05GEAD' && permissionModule.access > 0) {

            permissionModule.children.map(async (permissionSubmodule:PermissionsData) => {
              if (permissionSubmodule.id === 'S002V02S02PROV' && permissionSubmodule.access > 0) {

                this._dialog.open(AlertComponent, {
                  width: '500px',
                  maxWidth: '500px',
                  data: {
                    icon: 'warning',
                    title: `Registro Nuevo`,
                    description: `Se ha registrado un nuevo subcontratista en el Módulo de Gestión de personal, recursos y subcontratistas ¿Desea registrar el subcontratista como un proveedor en este momento?`
                  }
                }).afterClosed().subscribe(async (result) => {
                  if (result) {
                    let typeForm: TypeForm = { type: 'REGI', subcontract: `${idSubcontract.toString()}` }
                    let strTypeForm: string = JSON.stringify(typeForm);
                    let encTypeForm: string = await this._encService.encrypt(strTypeForm);
                   
                    this._router.navigate([`/sam/GEAD/PROV/ESWP/${encTypeForm}`]);
                  }
                });

                
              }
            });
          }
        });
      });

      this._socketService.equipmentAlert().subscribe(async (alertData) => {
        try{
          let permissionsStr = localStorage.getItem('permisos')!;
          let permissionsDec = await this._encService.decrypt(permissionsStr);
          let permissionsObj = JSON.parse(permissionsDec);
          let correctiveAutomaticActivationEnabled = false;

          for(const permission of permissionsObj.permissions){
            if(permission.id == 'S002V01M09GMCO'){
              let moduleEnabled = permission.access > 0;
              if(moduleEnabled){
                for(const permission0 of permission.children){
                  if(permission0.id == 'S002V01S01ORTR'){
                    let submoduleEnabled = permission0.access > 0;
                    if(submoduleEnabled){
                      for(const permission1 of permission0.children){
                        if(permission1.id == 'S002V01F02AABM'){
                          correctiveAutomaticActivationEnabled = permission1.access > 0;
                        }
                      }
                    }
                  }
                }
              }
            }
          }

          if(correctiveAutomaticActivationEnabled){
            let idUser = localStorage.getItem('idusuario')!;
            let equipment: EquipmentDetailsResponse = await lastValueFrom(this._equipmentManagementService.equipmentConsultOnly(
              alertData.equipment,
              idUser,
              1
            ));

            let notificationUsers = JSON.parse(alertData.notificationUsers);
            let notificationUsersDec: string[] = [];
            for(const userEnc of notificationUsers){
              let userDec = await this._encService.decrypt(userEnc);
              notificationUsersDec.push(userDec);
            }

            let idUserDec = await this._encService.decrypt(idUser);
            let correctiveOrder: CorrectiveWorkOrderDetailsResponse = await lastValueFrom(this._correctiveMaintenanceService.getWorkOrder(
              alertData.correctiveOrder,
              idUser,
              1
            ));

            let responsibleUserArr = correctiveOrder.response.ID_RESPONSABLE.split('(').reverse();
            let responsibleUserID = responsibleUserArr[0].replace(')', '');

            if(notificationUsersDec.includes(idUserDec) || responsibleUserID == idUserDec){
              let codeDec = await this._encService.decrypt(equipment.response.CODIGO);
              let tipoDec = await this._encService.decrypt(equipment.response.TIPO_EQUIPAMIENTO);
              let modeloDec = await this._encService.decrypt(equipment.response.MODELO);
              let idDec = await this._encService.decrypt(equipment.response.ID_EQUIPAMIENTO);
  
              let label = `Se ha detectado una medición que ha generado una órden de mantenimiento correctivo para el equipamiento`;
              let dialogRef = this._dialog.open(EquipmentAlertComponent, {
                width: '520px',
                maxWidth: '520px',
                disableClose: true,
                data: {
                  equipmentCode: `${codeDec} - ${tipoDec} - ${modeloDec} (${idDec})`,
                  label: label,
                }
              });
  
              dialogRef.afterClosed().subscribe(async (res) => {
                if(res == 'open-order'){
                  let dataObj = {
                    idOrder: correctiveOrder.response.ID_ORDEN,
                    actionFrom: 'notification'
                  };

                  let dataStr = JSON.stringify(dataObj);
                  let dataEnc = await this._encService.encrypt(dataStr);
                  this._router.navigate(['sam/GMCO/ORTR/GEOP'], {
                    queryParams: {
                      data: dataEnc,
                    }
                  });
                }
              });
            }
          }
        }catch(error: any){
          if(error.error == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (3).');
          }else if(error.error.msg == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (4).');
          }else{
            this._resourcesService.openSnackBar(error.error.msg);
          }
        }
      });

      this._socketService.notificationPublished().subscribe(async (notificationData) => {
        try{
          let audienceStr = await this._encService.decrypt(notificationData.audience);
          let audienceArr = JSON.parse(audienceStr);

          let idUser = localStorage.getItem('idusuario')!;
          let idUserDec = await this._encService.decrypt(idUser);

          if(audienceArr.includes(idUserDec)){            
            let notification: NotificationDetailsResponse = await lastValueFrom(this._notificationsService.getNotification(
              notificationData.idNotification,
              'N',
              idUser, 
              1
            ));

            if(notification.error){
              this._resourcesService.openSnackBar(notification.msg);
            }else{
              notification.response.FECHA = this._functionsService.getDateTimeHour(notification.response.FECREG);
              notification.response.FECREG_DISP = this._functionsService.notificationDate(notification.response.FECREG);
  
              let audienceArr = JSON.parse(notification.response.AUDIENCIA);
              for(const user of audienceArr as string[]){
                let userDec = await this._encService.decrypt(user);
                if(userDec == idUserDec){
                  let notificationsAux = this.totalNotifications;
                  notificationsAux.reverse();
                  notificationsAux.push(notification.response);
                  notificationsAux.reverse();
  
                  this.totalNotifications = notificationsAux;
                  this.notificationsForPanel.push(notification.response);
                  this.unreadNotifications++;
      
                  setTimeout(() => {
                    let divNotification = this._document.getElementById(`notification-${notification.response.ID_NOTIFICACION}`);
                    //Eliminar la clase de entrada
                    divNotification?.classList.remove('push-notification-enter');
                    //Añadir la clase de salida
                    divNotification?.classList.add('push-notification-out');
                    //Se elimina la notificación del arreglo después de esperar la animación
                    setTimeout(() => {
                      let notificationsAux: NotificationsListItem[] = [];
                      for(const notificationObj of this.notificationsForPanel){
                        if(notificationObj.ID_NOTIFICACION != notification.response.ID_NOTIFICACION){
                          notificationsAux.push(notificationObj);
                        }
                      }
                
                      this.notificationsForPanel = notificationsAux;
                    }, 800);
                  }, 5000);
                }
              }
            }
          }
        }catch(error: any){          
          if(error.error == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (5).');
          }else if(error.error.msg == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (6).');
          }else{
            this._resourcesService.openSnackBar(error.error.msg);
          }
        }
      });

      this._socketService.newSessionSaved().subscribe(async (sessionsStr) => {
        try{
          let idUser = localStorage.getItem('idusuario');
          if(idUser != null && idUser != undefined && idUser != ''){
            let sessionsArr = JSON.parse(sessionsStr);
            let sessionsCount = 0;
            let idUserDec = await this._encService.decrypt(idUser);
    
            for(const session of sessionsArr){
              let sessionUsr = await this._encService.decrypt(session.user);
              if(sessionUsr == idUserDec){
                sessionsCount++;
              }
            }
            
            let activeSessionsNumber: ActiveSessionsNumberResponse = await lastValueFrom(this._systemAdminService.getActiveSessionsNumber(idUser, 1));
            if(activeSessionsNumber.error){
              this._resourcesService.openSnackBar(activeSessionsNumber.msg);
            }else{
              this.enabledSessions = activeSessionsNumber.response.active_sessions_number;
              this.usedSessions = sessionsCount;
            }
          }
        }catch(error: any){
          if(error.error == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (7).');
          }else if(error.error.msg == undefined){
            this._resourcesService.openSnackBar('Ocurrió un error inesperado (8).');
          }else{
            this._resourcesService.openSnackBar(error.error.msg);
          }
        }
      });

      this._socketService.updateEnabledSessions().subscribe(data => {
        this.enabledSessions = parseInt(data);
      });

      this._socketService.timerEnabled().subscribe((status: boolean) => {
        this.maintenanceActivated = status;
      });
      
      this._socketService.refreshModules().subscribe(async () => {
        let menuUpdated: NestedMenuInterface = await lastValueFrom(this._modulesService.getMenu(idUser!, 1));
        if(menuUpdated.error){
          this._resourcesService.openSnackBar(menuUpdated.msg);
        }else{
          let allowedModules: MenuModules[] = [];
          for(const allowedModule of this.menuItems){
            let idModuleDec = await this._encService.decrypt(allowedModule.ID_MODULO);
            let module: MenuModules = {
              ID_MODULO: allowedModule.ID_MODULO,
              ID_MODULO_DEC: idModuleDec,
              NOMBRE_MODULO: allowedModule.NOMBRE_MODULO,
              ICONO_MODULO: allowedModule.ICONO_MODULO,
              ICONO_PERSONALIZADO: allowedModule.ICONO_PERSONALIZADO,
              ARCHIVO_ICONO_PERSONALIZADO: allowedModule.ARCHIVO_ICONO_PERSONALIZADO,
              SUBMODULES: allowedModule.SUBMODULES,
              MENUS: allowedModule.MENUS
            };

            allowedModules.push(module);
          }
          
          let updatedModules: MenuModules[] = [];
          for(const moduleUpdated of menuUpdated.response){
            let idModuleDec = await this._encService.decrypt(moduleUpdated.ID_MODULO);
            let moduleFilt = allowedModules.filter(item => item.ID_MODULO_DEC == idModuleDec);

            if(moduleFilt.length > 0){
              let customIconEnc = await this._encService.isEncrypted(moduleUpdated.ICONO_PERSONALIZADO);
              let customIcon = customIconEnc ? await this._encService.decrypt(moduleUpdated.ICONO_PERSONALIZADO) : moduleUpdated.ICONO_PERSONALIZADO;
              
              if(customIcon == 'S'){
                let iconFileURL = await lastValueFrom(this._gdelService.getPublicDocumentUrl(
                  moduleUpdated.ARCHIVO_ICONO_PERSONALIZADO!,
                  idUser!,
                  1
                ));

                this._matIconRegistry.addSvgIcon(
                  moduleUpdated.ICONO_MODULO,
                  this._domSanitizer.bypassSecurityTrustResourceUrl(iconFileURL.response.public_uri)
                );
              }

              let module: MenuModules = {
                ID_MODULO: moduleUpdated.ID_MODULO,
                NOMBRE_MODULO: moduleUpdated.NOMBRE_MODULO,
                ICONO_MODULO: moduleUpdated.ICONO_MODULO,
                ICONO_PERSONALIZADO: customIcon,
                ARCHIVO_ICONO_PERSONALIZADO: moduleUpdated.ARCHIVO_ICONO_PERSONALIZADO,
                SUBMODULES: moduleUpdated.SUBMODULES,
                MENUS: moduleUpdated.MENUS
              };

              updatedModules.push(module);
            }
          }
          
          this.menuItems = updatedModules;
        }
      });

      this._socketService.getSessions();
      this._socketService.getTimerEnabled();

      let userName = localStorage.getItem('nombre_usuario');
      let name = await this._encService.decrypt(userName!);

      await this.getNotifications();
      
      this.userName = name;
      this.nestedMenu = menu.response;
      
      this.isLoading = false;
      this.checkCatalogues();

      setInterval(() => {
        let notificationsAux: NotificationsListItem[] = [];
        for(const notification of this.totalNotifications){
          notification.FECREG_DISP = this._functionsService.notificationDate(notification.FECREG);
          notificationsAux.push(notification);
        } 

        this.totalNotifications = notificationsAux;
      }, 30000);
    }catch(error: any){
      console.log(error);
      if(error.error == undefined){
        this.openDialog('Ocurrió un error inesperado (9).');
      }else if(error.error.msg == undefined){
        this.openDialog('Ocurrió un error inesperado (10).');
      }else{
        this.openDialog(error.error.msg);
      }

      this.errorsCont++;
    }
  }

  public onResize(){
    this.title = window.innerWidth <= 1050 ? 'SAM L1' : 'Sistema de Ayuda al Mantenimiento L1'.toUpperCase();
  }

  openDialog(msg: string){
    let msgFin = this.errorsCont < 3 ? msg : 'El error persiste, por favor contacte al departamenteo de TI para solucionarlo.';
    let _dialogRef = this._dialog.open(AlertComponent, {
      width: '300px',
      maxWidth: '300px',
      data: {
        icon: "error",
        title: '¡Error!',
        description: msgFin,
      },
    });

    _dialogRef.afterClosed().subscribe((_) => {
      if(this.errorsCont < 3){
        location.reload();
      }else{
        this.logout();
      }
    });
  }

  logout () {
    this._loginDataService.logout();
  }

  openAdviceAlert(advice: Advice){
    this._dialog.open(AdviceAlertComponent, {
      data: advice
    });
  }

    openUploadData(){
    this._router.navigate(['sam/initial-data-upload'])
  }

  async getNotifications(){
    try{
      let idUser = localStorage.getItem('idusuario')!;
      let notifications: NotificationsListResponse = await lastValueFrom(this._notificationsService.getNotificationsByUser(idUser, 1));

      if(notifications.error){
        this.openDialog(notifications.msg);
      }else{
        let notificationsArr: NotificationsListItem[] = [];
        let idUserDec = await this._encService.decrypt(idUser);

        for(const notification of notifications.response){
          let scopeArr = JSON.parse(notification.ALCANCE);
          for(const item of scopeArr){
            let userDec = await this._encService.decrypt(item.USUARIO);
            if(userDec == idUserDec && item.ESTADO == 'No leído'){
              this.unreadNotifications++;
              notification.READED = false;
            }else if(userDec == idUserDec && item.ESTADO == 'Leído'){
              notification.READED = true;
            }
          }
          
          notification.FECREG_DISP = this._functionsService.notificationDate(notification.FECREG)!;
          notificationsArr.push(notification);
        }

        this.totalNotifications = notificationsArr;
      }
    }catch(error: any){
      if(error.error == undefined){
        this.openDialog('Ocurrió un error inesperado (11).');
      }else if(error.error.msg == undefined){
        this.openDialog('Ocurrió un error inesperado (12).');
      }else{
        this.openDialog(error.error.msg);
      }
    }
  }

  private async checkCatalogues() {
    try{
      const encPermisos:string = localStorage.getItem('permisos')!;
      if(encPermisos != '' && encPermisos != undefined && encPermisos != null){
        const strPermisos: string = await this._encService.decrypt(encPermisos);
        const arrPermisos: Permissions = JSON.parse(strPermisos);

        for(const module of arrPermisos.permissions){
          if(module.id == 'S002V01M05GEAD' && module.access > 0){
            for(const submodule of module.children){
              if(submodule.id == 'S002V02S02PROV' && submodule.access > 0){
                for(const func of submodule.children){
                  if(func.id === 'S002V01F05GVPA' && func.access == 2){
                    let catalogCoins = localStorage.getItem('catalogo_moneda');
                    if(catalogCoins === null){
                      const idUser:string = this._resourcesService.getUser();
                      const line: number = this._resourcesService.getLineNumber();

                      let responseData: ResponseDataCatalogueCoins = await lastValueFrom(this._cataloguesService.getGeneralCatalogueInfo(
                        'c_Moneda', 
                        5, 
                        idUser, 
                        line
                      ));

                      if (!responseData.error) {    
                        let arrCataloguesCoinsDocument:Array<CatalogueCoinsDocument> = responseData.response;
                        let arrCataloguesCoins:Array<CatalogueCoins> = arrCataloguesCoinsDocument.map((cataloguesCoins:CatalogueCoinsDocument) =>  {
                          return {
                            C_MONEDA: cataloguesCoins.c_Moneda,
                            DESCRIPCION: cataloguesCoins.Descripción,
                            DECIMALES: cataloguesCoins.Decimales,
                            PORCENTAJE_VARIACION: cataloguesCoins.Porcentaje_variación,
                            FECHA_INICIO_DE_VIGENCIA: cataloguesCoins.Fecha_inicio_de_vigencia,
                            FECHA_FIN_DE_VIGENCIA: cataloguesCoins.Fecha_fin_de_vigencia,
                          }
                        });
                        arrCataloguesCoins = arrCataloguesCoins.filter((cataloguesCoins:CatalogueCoins) =>  
                          cataloguesCoins.C_MONEDA !== null && cataloguesCoins.DESCRIPCION !== null
                        );

                        const strCataloguesCoins:string = JSON.stringify(arrCataloguesCoins);
                        const encCataloguesCoins:string = await this._encService.encrypt(strCataloguesCoins);
                        localStorage.setItem('catalogo_moneda', encCataloguesCoins);
                      } else {
                        this._resourcesService.openSnackBar(`${responseData.msg}`);
                      } 
                    }
                  }
                }
              }
            }
          }
        }
      }
    }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);
      }
    }
  }

  openMyProfile(){
    this._dialog.open(MyProfileComponent, {
      width: '580px',
      maxWidth: '580px',
    });
  }

  openNotification(idNotification: string, isFromSidenav: boolean){
    let notificationFilt = this.totalNotifications.filter(item => item.ID_NOTIFICACION == idNotification);
    if(notificationFilt.length > 0){
      let notification = notificationFilt[0];
      notification.READED = true;

      let notificationsAux: NotificationsListItem[] = [];
      for(const notificationObj of this.totalNotifications){
        if(notificationObj.ID_NOTIFICACION == notification.ID_NOTIFICACION){
          notificationsAux.push(notification);
        }else{
          notificationsAux.push(notificationObj);
        }
      }

      this.totalNotifications = notificationsAux;
      this.unreadNotifications--;
    }
    
    this.closeNotification(idNotification);
    let dialogRef = this._dialog.open(NotificationDialogComponent, {
      width: '520px',
      maxWidth: '520px',
      data: {
        idNotification: idNotification,
      }
    });

    dialogRef.afterClosed().subscribe(res => {
      if(res != null && res != undefined && res != ''){
        let resArr = res.split('|');
        if(resArr.length < 2){
          this._resourcesService.openSnackBar('La acción seleccionada es inválida.');
        }else if(resArr[0] == 'go'){
          this.navigateFromNotification(resArr[1]);
        }

      }

      if(isFromSidenav){
        this.sidenav?.close();
      }
    });
  }

  closeNotification(id: string){
    let notification = this._document.getElementById(`notification-${id}`);
    //Eliminar la clase de entrada
    notification?.classList.remove('push-notification-enter');
    //Añadir la clase de salida
    notification?.classList.add('push-notification-out');
    //Se elimina la notificación del arreglo después de esperar la animación
    setTimeout(() => {
      let notificationsAux: NotificationsListItem[] = [];
      for(const notificationObj of this.notificationsForPanel){
        if(notificationObj.ID_NOTIFICACION != id){
          notificationsAux.push(notificationObj);
        }
      }

      this.notificationsForPanel = notificationsAux;
    }, 800);
  }

  private async navigateFromNotification(routeEnc: string){
    let routeDec = await this._encService.decrypt(routeEnc);
    this._router.navigate([`sam/${routeDec}`]);
  }

  async navigate(modID: string){
    let route = modID.substring(10, modID.length);
    this.modulesActivated = false;    
    this._router.navigate([`sam/${route}`]);
  }

  closeNestedMenu(){
    this.modulesActivated = false;
  }
}
