import { Component, Inject, Input, OnInit } from '@angular/core';
import { ControlPanelDetails, ControlPanelDetailsResponse, PanelCountersListItem, PanelElements } from '../../../../interfaces/control-panel.interface';
import { UserResponse } from '../../../../interfaces/users.interface';
import { CounterChartConfiguration } from '../add-elements/add-elements.component';
import { DOCUMENT } from '@angular/common';
import { SocketService } from '../../../../services/socket.service';
import { EncService } from '../../../../services/enc.service';
import { CountersActivatorsService } from '../../../../services/counters-activators.service';
import { FunctionsService } from '../../../../services/functions.service';
import { ResourcesService } from '../../../../services/resources.service';
import { MatDialog } from '@angular/material/dialog';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { ControlPanelService } from '../../../../services/control-panel.service';
import { DocumentManagementService } from '../../../../services/document-management.service';
import { lastValueFrom } from 'rxjs';
import { CounterMeasuresListResponse } from '../../../../interfaces/counters-activators.interface';
import { MeasuresHistoryComponent } from '../../../corrective-maintenance/operations-management/corrective-order-form/measures-history/measures-history.component';

@Component({
    selector: 'app-control-panel-view',
    templateUrl: './control-panel-view.component.html',
    styleUrl: './control-panel-view.component.css',
    standalone: false
})
export class ControlPanelViewComponent implements OnInit {
  @Input() isPreview: boolean;
  @Input() controlPanel: ControlPanelDetails | null;
  @Input() panelElements: PanelElements[];
  @Input() users: UserResponse[];
  @Input() countersIndicators: PanelCountersListItem[];

  panelElementsIDS: string[];
  usersConnected: UserResponse[];
  countersCharts: CounterChartConfiguration[];

  isLoading: boolean;
  hasError: boolean;
  errorStr: string;
  screenSize: number;

  constructor(
    @Inject(DOCUMENT) private _document: Document,
    private _socketService: SocketService,
    private _encService: EncService,
    private _countersActivatorsService: CountersActivatorsService,
    private _functionsService: FunctionsService,
    private _resourcesService: ResourcesService,
    private _dialog: MatDialog,
    private _matIconRegistry: MatIconRegistry,
    private _domSanitizer: DomSanitizer,
    private _controlPanelService: ControlPanelService,
    private _documentManagementService: DocumentManagementService,
  ) {
    this.isPreview = false;
    this.controlPanel = null;
    this.panelElements = [];
    this.users = [];
    this.countersIndicators = [];

    this.panelElementsIDS = [];
    this.usersConnected = [];
    this.countersCharts = [];

    this.isLoading = true;
    this.hasError = false;
    this.errorStr = '';
    this.screenSize = window.innerWidth;
    
    this._matIconRegistry.addSvgIcon(
      'xls',
      this._domSanitizer.bypassSecurityTrustResourceUrl(window.location.origin + "/assets/img/custom_icons/xls.svg")
    );
  }

  ngOnInit(): void {
    for(const element of this.panelElements){
      this.panelElementsIDS.push(element.idElement);
    }

    this.initSocketListener();
    this.initIndicators();
  }

  initSocketListener(){
    this._socketService.currentConnections().subscribe(async (connections) => {
      let idUser = localStorage.getItem('idusuario')!;
      let idUserDec = await this._encService.decrypt(idUser);
      let connectionsStr = `${connections}`;
      let connectionsArr = JSON.parse(connectionsStr);

      for(const connection of connectionsArr){
        let connectionArr = connection.split('.');
        let idConnectedUserDec = await this._encService.decrypt(connectionArr[0]);
        if(idConnectedUserDec != idUserDec){
          let userFilt = this.users.filter(user => user.IDUSUARIO == idConnectedUserDec);
          if(userFilt.length > 0){
            let alreadyConnected = this.usersConnected.filter(user => user.IDUSUARIO == idConnectedUserDec);
            if(alreadyConnected.length < 1){
              let colorR = Math.ceil(Math.random() * 255);
              let colorG = Math.ceil(Math.random() * 255);
              let colorB = Math.ceil(Math.random() * 255);

              userFilt[0].COLOR = `rgb(${colorR}, ${colorG}, ${colorB})`;
              this.usersConnected.push(userFilt[0]);
            }
          }
        }
      }
    });

    this._socketService.newConnection().subscribe(async (connections) => {
      let connectionsStr = `${connections}`;
      let connectionsArr = JSON.parse(connectionsStr);

      for(const connection of connectionsArr){
        let connectionArr = connection.split('.');
        let connectionDec = await this._encService.decrypt(connectionArr[0]);
        let userFilt = this.users.filter(user => user.IDUSUARIO == connectionDec);

        if(userFilt.length > 0){
          let alreadyConnected = this.usersConnected.filter(user => user.IDUSUARIO == connectionDec);
          if(alreadyConnected.length < 1){
            let colorR = Math.ceil(Math.random() * 255);
            let colorG = Math.ceil(Math.random() * 255);
            let colorB = Math.ceil(Math.random() * 255);

            userFilt[0].COLOR = `rgb(${colorR}, ${colorG}, ${colorB})`;
            this.usersConnected.push(userFilt[0]);
          }
        }
      }
    });

    this._socketService.disconnection().subscribe(async (connections) => {
      let connectionsStr = `${connections}`;
      let connectionsArr = JSON.parse(connectionsStr);
      let idUser = localStorage.getItem('idusuario')!;
      let idUserDec = await this._encService.decrypt(idUser);
      let connectionsArrDec: string[] = [];

      for(const connection of connectionsArr){
        let connectionArr = connection.split('.');
        let connectionDec = await this._encService.decrypt(connectionArr[0]);

        if(connectionDec != idUserDec){
          connectionsArrDec.push(connectionDec);
        }
      }

      let connectedUsersAux: UserResponse[] = [];
      for(const connected of connectionsArrDec){
        let userFilt = this.users.filter(user => user.IDUSUARIO == connected);
        if(userFilt.length > 0){
          let alreadyConnected = connectedUsersAux.filter(user => user.IDUSUARIO == connected);
          if(alreadyConnected.length < 1){
            connectedUsersAux.push(userFilt[0]);
          }
        }
      }

      this.usersConnected = connectedUsersAux;
    });
    
    this._socketService.getConnections();

    this._socketService.updatePanelElements().subscribe(async (idPanel) => {
      let idPanelEnc = `${idPanel}`;
      let idUser = localStorage.getItem('idusuario')!;
      let panel: ControlPanelDetailsResponse = await lastValueFrom(this._controlPanelService.getPanel(idPanelEnc, idUser, 1));
      
      if(!panel.error){
        this.countersCharts = [];
        this.panelElements = [];
        this.panelElementsIDS = [];

        let elements: PanelElements[] = JSON.parse(panel.response.INDICADORES_RELACIONADOS);
        for(const element of elements){
          element.idElement = await this._encService.decrypt(element.idElement);
          element.module = await this._encService.decrypt(element.module);

          await this.processElement(element);

          this.panelElements.push(element);
          this.panelElementsIDS.push(element.idElement);
        }
      }
    });
  }

  async initIndicators(){
    try{
      for(const element of this.panelElements){
        await this.processElement(element);
      }
      
      this.isLoading = false;
      this.startHTML();
    }catch(error: any){
      if(error.error == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else if(error.error.msg == undefined){
        this.errorStr = 'Ocurrió un error inesperado.';
      }else{
        this.errorStr = error.error.msg;
      }

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

  async processElement(element: PanelElements){
    switch(element.module){
      case 'S002V01M06COAC':
        let indicator = this.countersIndicators.filter(indicator => indicator.ID_CONTADOR == element.idElement);
        if(indicator.length > 0){
          let codeEquipmentDec = await this._encService.decrypt(indicator[0].CODIGO_EQUIPAMIENTO);
          let idEquipmentDec = await this._encService.decrypt(indicator[0].ID_EQUIPAMIENTO);

          let measuresVals: number[] = [];
          let labels: string[] = [];

          for(const measure of indicator[0].LAST_MEASURES){
            measuresVals.push(measure.VALOR);
            labels.push(this._functionsService.getDateTimeHour(measure.HORA_REGISTRO));
          }
      
          let colorR = Math.ceil(Math.random() * 255);
          let colorG = Math.ceil(Math.random() * 255);
          let colorB = Math.ceil(Math.random() * 255);
  
          let dataset = {
            data: measuresVals,
            label: 'Mediciones',
            backgroundColor: `rgba(${colorR},${colorG},${colorB},0.2)`,
            borderColor: `rgba(${colorR},${colorG},${colorB},1)`,
            pointBackgroundColor: `rgba(${colorR},${colorG},${colorB},1)`,
            pointBorderColor: '#fff',
            pointHoverBackgroundColor: '#fff',
            pointHoverBorderColor: `rgba(${colorR},${colorG},${colorB},0.8)`,
            fill: 'origin',
          };

          let counterChartConfig: CounterChartConfiguration = {
            counterID: indicator[0].ID_CONTADOR,
            counterEquipment: `${codeEquipmentDec} - ${indicator[0].TIPO_EQUIPAMIENTO} - ${indicator[0].MODELO_EQUIPAMIENTO} (${idEquipmentDec})`,
            chartData: {
              datasets: [dataset],
              labels: labels
            },
            chartOptions: {
              elements: {
                line: {
                  tension: 0.5
                },
              },
              scales: {
                y: {
                  position: 'left'
                },
              },
              plugins: {
                legend: { display: true },
                annotation: {
                  annotations: [
                    {
                      type:'line',
                      scaleID: 'x',
                      borderColor: 'white',
                      borderWidth: 2,
                      label: {
                        display: true,
                        position: 'center',
                        font: {
                          weight: 'bold',
                        }
                      }
                    }
                  ]
                }
              }
            },
            chartType: 'line',
            isAssigned: false,
          };

          this.countersCharts.push(counterChartConfig);

          //Inicialización del socket por cada contador
          this._socketService.refreshCounterMeasures().subscribe(async (data: any) => {
            let idSocketCounterDec = await this._encService.decrypt(data.idCounter);
            if(idSocketCounterDec == indicator[0].ID_CONTADOR){
              let idUser = localStorage.getItem('idusuario')!;
              let measures: CounterMeasuresListResponse = await lastValueFrom(this._countersActivatorsService.counterConsultMeasures(
                data.idCounter, 'FECREG', 'D',
                10, 0, idUser, 1
              ));

              if(measures.error){
                this._resourcesService.openSnackBar(measures.msg);
              }else{
                let measuresVals: number[] = [];
                let labels: string[] = [];
        
                for(const measure of measures.response){
                  measuresVals.push(measure.VALOR);
                  labels.push(this._functionsService.getDateTimeHour(measure.HORA_REGISTRO));
                }

                let chartFilt = this.countersCharts.filter(chart => chart.counterID == indicator[0].ID_CONTADOR);
                if(chartFilt.length > 0){
                  let backgroundColor = chartFilt[0].chartData.datasets[0].backgroundColor;
                  let borderColor = chartFilt[0].chartData.datasets[0].borderColor;
                  let pointBackgroundColor = chartFilt[0].chartData.datasets[0].borderColor;
                  let pointHoverBorderColor = chartFilt[0].chartData.datasets[0].borderColor!.toString().replace(',1)', ',0.8)');
      
                  let dataset = {
                    data: measuresVals,
                    label: 'Mediciones',
                    backgroundColor: backgroundColor!.toString(),
                    borderColor: borderColor!.toString(),
                    pointBackgroundColor: pointBackgroundColor!.toString(),
                    pointBorderColor: '#fff',
                    pointHoverBackgroundColor: '#fff',
                    pointHoverBorderColor: pointHoverBorderColor,
                    fill: 'origin',
                  };

                  chartFilt[0].chartData = {
                    datasets: [dataset],
                    labels: labels
                  };
                }
              }
            }
          });
        }
      break;
    }
  }

  startHTML(){
    setTimeout(() => {
      let usersList = this._document.getElementById('users-list-indicator');
      if(usersList != null){
        usersList.addEventListener('wheel', (e: any) => {
          if(this.screenSize <= 535){
            if(e.deltaY > 0){
              usersList!.scrollLeft += 10;
              e.preventDefault();
            }else{
              usersList!.scrollLeft -= 10;
              e.preventDefault();
            }
          }
        });
      }

      let indicatorsContainer = this._document.getElementById('indicators-container');
      if(indicatorsContainer != null){
        indicatorsContainer.addEventListener('wheel', (e: any) => {
          if(this.controlPanel!.ORIENTACION == 'Horizontal'){
            if(e.deltaY > 0){
              indicatorsContainer!.scrollLeft += 20;
              e.preventDefault();
            }else{
              indicatorsContainer!.scrollLeft -= 20;
              e.preventDefault();
            }
          }
        });
      }
    }, 250);
  }

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

  async openMeasuresDialog(idCounter: string){
    let idCounterEnc = await this._encService.encrypt(idCounter);
    this._dialog.open(MeasuresHistoryComponent, {
      width: '720px',
      maxWidth: '720px',
      disableClose: true,
      data: {
        idCounter: idCounterEnc,
      }
    })
  }

  async exportExcelData(module: string, indicator: string){
    try{
      this._resourcesService.openSnackBar('Generando archivo...');

      let idUser = localStorage.getItem('idusuario')!;
      let idModule = await this._encService.encrypt(module);
      let indicatorEnc = await this._encService.encrypt(indicator);

      let excelDoc = await lastValueFrom(this._controlPanelService.getInfoToExcel(indicatorEnc, idModule, idUser, 1));
      let downloadToken = await lastValueFrom(this._documentManagementService.getDownloadToken(
        excelDoc.response.report,
        idUser,
        1
      ));

      let idFile = await this._encService.decrypt(excelDoc.response.report);
      let download = this._document.getElementById('download') as HTMLAnchorElement;
      download.href = `http://git.ittec.mx/sam/public/api/download-file/${downloadToken.response.TOKEN}/${idUser}/1`;
      download.download = idFile;
      download.click();
    }catch(error: any){
      if(error.error == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else if(error.error.msg == undefined){
        this._resourcesService.openSnackBar('Ocurrió un error inesperado.');
      }else{
        this._resourcesService.openSnackBar(error.error.msg);
      }
    }
  }
}
