import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, ElementRef } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute } from '@angular/router';
import { Chart, ChartDataset, DatasetChartOptions } from 'chart.js';
import { lastValueFrom } from 'rxjs';
import { DataEquipment, GetFailureByEquipment, GetFailureList, ResponseDataGetFailureByEquipment } from 'src/app/interfaces/ANFA/failure.interface';
import { EncService } from 'src/app/services/enc/enc.service';
import { FailureService } from 'src/app/services/failure-analysis/failure.service';
import { ResourcesService } from 'src/app/services/resources/resources.service';
import * as colores from 'src/assets/json/colores.json';
import { FailureCalculationComponent } from '../failure-calculation/failure-calculation.component';

export interface PeriodData{
  year?: number;
  month?: string;
  disabled: boolean;
}

@Component({
  selector: 'app-failure-chart',
  templateUrl: './failure-chart.component.html',
  styleUrls: ['./failure-chart.component.css']
})
export class FailureChartComponent implements OnInit {

  public arrStartYears: Array<PeriodData>;
  public arrEndYears: Array<PeriodData>;
  public arrStartMonths: Array<PeriodData>;
  public arrEndMonths: Array<PeriodData>;

  public formGroupPeriodicity: FormGroup;
  public myChart!: Chart;

  public arrFailures: Array<GetFailureList> = [];
  public arrSelectedFailures:  Array<GetFailureList> = [];
  public dataEquipment!: DataEquipment;
  public arrMonth: Array<string> = ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];

  public currentDate: Date = new Date();

  constructor(
    private elementRef: ElementRef,
    public resourcesService: ResourcesService,
    private _failureService: FailureService,
    private _activatedRouter: ActivatedRoute,
    private _encService: EncService,
    private _dialog: MatDialog,
  ) {
    this.arrStartYears = [];
    for (let year = 2010; year < new Date().getFullYear() + 1; year++) {
      this.arrStartYears.push({year: year, disabled: false});
    }
    this.arrEndYears = [];
    for (let year = 2010; year < new Date().getFullYear() + 1; year++) {
      this.arrEndYears.push({year: year, disabled: false});
    }
    this.arrStartMonths = [];
    this.arrMonth.forEach(month => {
      this.arrStartMonths.push({month: month, disabled: false});
    });
    this.arrEndMonths = [];
    this.arrMonth.forEach(month => {
      this.arrEndMonths.push({month: month, disabled: false});
    });
    this.formGroupPeriodicity = this.createFormGroupPeriodicity();
  }

  ngOnInit() {
    // Se obtienen los datos del equipamiento de la URL
    this.getDataEquipment();
  }

  // Método para obtener los datos del equipamiento
  private async getDataEquipment(){
    // Se obtienen los del equipamiento de la URL
    let encData:string = this._activatedRouter.snapshot.paramMap.get('dataEquipment')!;
    // Se desencriptan los datos y pasan a pasar a un objeto
    let strData:string = await this._encService.desencriptar(encData);
    this.dataEquipment = JSON.parse(strData);
    // Se guarda la información de los equipamientos
    this.equipment?.setValue(this.dataEquipment.CODIGO_EQUIPAMIENTO);
    // Se obtienen la información completa de la fallas
    this.getFailuresByEquipment();
  }

  // Método para obtener la información de las fallas
  private async getFailuresByEquipment() {
    await lastValueFrom(this._failureService.getFailureByEquipment({
      CODIGO_EQUIPAMIENTO: this.dataEquipment.CODIGO_EQUIPAMIENTO,
      NUMERO_LINEA: "1"
    })).then(
      (responseData: ResponseDataGetFailureByEquipment) => {
        // Se guardan la información de las fallas
        this.arrFailures = responseData.response;
        // Se seleccionan los datos de las fallas seleccionadas
        this.arrFailures.map((failure:GetFailureList) => {
          if (failure.ID_FALLA === this.dataEquipment.ID_FALLA) {
            this.arrSelectedFailures.push(failure);
          }
        });
        //
        this.changeListFailure();

      }, (error: HttpErrorResponse) => this.resourcesService.checkErrors(error)
    );
  }

  // Método para generar el diagrama
  public changeListFailure() {
    // Se obtienen el rango de fechas del formulario
    let periodStart: Date = this.periodStart?.value;
    let periodEnd: Date = this.periodEnd?.value;

    // Se obtienen los colores para las lineas
    const jsonColors = colores;
    const arrColors: Array<string> = jsonColors.colores

    // Se el rango de fechas tiene datos correctos, entonces prosigue.
    if (periodStart !== null && periodEnd !== null) {

      // Obtener los meses que hay en el rango de fechas
      let diffDate:number = periodEnd.getTime() - periodStart.getTime();
      let minutes:number = diffDate * 0.0000166667;
      let month:number = Math.ceil(minutes * 0.0000228154);

      // Asignación de los datos a los gráficos
      let arrDataset: Array<ChartDataset> = [];
      let arrSelectedMonth: Array<string> = [];

      // Iteración de la lista de fallas seleccionadas
      this.arrSelectedFailures.map((failureList:GetFailureList, indexFailure:number) => {
        arrSelectedMonth = [];
        // Se obtiene el año inicial del rango del periodo
        let yearStart: number = periodStart.getFullYear();
        // Se obtiene el mes inicial del rango del periodo
        let monthStart: number = periodStart.getMonth();
        let arrData: Array<number> = [];
        for (let index = 0; index < month; index++) {
          let cont:number = 0;
          arrSelectedMonth.push(this.arrMonth[monthStart]);
          failureList.LISTA.map((failure: GetFailureByEquipment) => {
            let arrDateFailure: Array<string> = failure.FECHA_FALLA.split('-');
            let yearFailure:number = parseInt(arrDateFailure[0]);
            let monthFailure:number = parseInt(arrDateFailure[1]) - 1;
            if ( monthStart === monthFailure && yearStart == yearFailure ) {
              cont++;
            }
          });
          arrData.push(cont);
          monthStart++;
          if (monthStart === 12) {
            monthStart = 0;
            yearStart++;
          }
        }

        arrDataset.push({
          label: failureList.FALLA,
          data: arrData,
          fill: false,
          borderColor: arrColors[indexFailure],
          backgroundColor: arrColors[indexFailure],
          tension: 0.1
        });
      });

      if (this.myChart !== undefined) {
        this.myChart.destroy();
      }
      this.createChart(arrSelectedMonth, arrDataset);
    }

  }

  // Método para generar la gráfica
  private createChart(arrLabels: Array<string>, arrDatasets: Array<ChartDataset>) {
    let htmlRef = this.elementRef.nativeElement.querySelector(`#myChart`);
    this.myChart = new Chart(htmlRef, {
      type: 'line',
      data: {
        labels: arrLabels,
        datasets: arrDatasets
      }
    });
  }

  // Método para la creación del formulario
  private createFormGroupPeriodicity() {
    return new FormGroup({
      periodStart: new FormControl(new Date( this.currentDate.getFullYear(), 0, 1 ), Validators.required),
      periodEnd: new FormControl(this.currentDate, Validators.required),
      equipment: new FormControl('', Validators.required),
    });
  }

  public openDialog() {
    this._dialog.open(FailureCalculationComponent, {
      data: this.arrSelectedFailures[0],
      width: '600px',
      disableClose: true,
    });
  }

  get periodStart() { return this.formGroupPeriodicity.get('periodStart'); }
  get periodEnd() { return this.formGroupPeriodicity.get('periodEnd'); }
  get equipment() { return this.formGroupPeriodicity.get('equipment'); }
}


