import { Component, OnInit, ViewChild,OnChanges } from '@angular/core';
import { Chart, ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import { Label, BaseChartDirective } from 'ng2-charts';
import { MeasuresService } from 'src/app/services/measures.service';
import { PlantsService } from 'src/app/services/plants.service';
import { LogsService } from 'src/app/services/logs.service';

import { OrganizationsService } from '@app/services/organizations.service';
import { ActivatedRoute } from '@angular/router';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import Swal from 'sweetalert2';
import { HttpClient } from '@angular/common/http';
import { formatDate } from '@angular/common';

import {AngularMyDatePickerDirective,IAngularMyDpOptions, IMyDateModel} from 'angular-mydatepicker';
import printJS from 'print-js'

@Component({
  selector: 'app-assets',
  templateUrl: './assets.component.html',
  styleUrls: ['./assets.component.scss']
})

export class AssetsComponent implements OnInit {
  
  title = "Plantas";

  // General var declarations
  organizationId:string;
  listAssets:any;
  eProduced:any;
  error:boolean;
  errorMessage:string;
  errortest:any;
  metersKeys:any;
  metersValues:any;
  view:string;
  energyDay=0;
  energyWeek=0;
  energyMonth=0;
  energyYear=0;
  environment:any;
  environmentCO2:any;
  environmentHouse:any;
  environmentFuel:any;
  isActive:[boolean,boolean,boolean,boolean]; //Activated param (chart)
  chartActive:[boolean,boolean,boolean,boolean]
  initialLoad: boolean = true;

  // For daterange
  daysLabels:any = {su: 'Dom', mo: 'Lun', tu: 'Mar', we: 'Mie', th: 'Jue', fr: 'Vie', sa: 'Sab'};
  monthsLabels:any = { 1: 'Ene', 2: 'Feb', 3: 'Mar', 4: 'Abr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Ago', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dic' };
  todayBtnTxt:string = 'Hoy';
  myDpOptions: IAngularMyDpOptions = {
    dateRange: false,
    dateFormat: 'dd/mm/yyyy',
    dayLabels: this.daysLabels,
    monthLabels: this.monthsLabels,
  };
  myDateInit: boolean = true;
  model: IMyDateModel = null;

  // For MatDataTable
  metersData:any;
  initialDate:any;
  tableData: any;
  showTable: boolean;
  displayedColumns: any;
  tableData2: any[];
  array1: any[];
  array2: any[];
  array3: any[];
  dataSource = new MatTableDataSource(this.tableData2);  
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort: MatSort;

  // For chartjs
  chartjs:boolean;
  chart1: Chart;
  chart1Type: string;
  barChartColors:any = ['#5f86b0','#a9d0ea', '#00a65a', '#a7c957', '#f2e8cf', '#3c8dbc', '#f56954', '#ee964b']
  borderChartColors:any = ['#4573a5','#a2cae4', '#018247', '#91b43d', '#d3cbb7', '#539dc8', '#e4604c', '#d38d51']
  public barChartType: ChartType;
  public barChartLegend:boolean;
  public barChartLabels: Label[];
  public barChartOptions: ChartOptions;
  public barChartData: ChartDataSets[];
  @ViewChild("baseChart",null) chart: BaseChartDirective;

  
  // Get selected asset
  constructor(
    private orgService: OrganizationsService, 
    private route: ActivatedRoute, 
    private plantsService: PlantsService,
    private http: HttpClient,
    private logsService: LogsService,
    private measService: MeasuresService) {
      
      this.route.queryParams.subscribe(params => {
        this.organizationId = params['id'];
      });
      
      Swal.fire({
        allowOutsideClick: false,
        type: 'info',
        text: 'Espere por favor...'
      });
      Swal.showLoading();
  }

  ngOnInit() {
    // Default date is today and set it on a string var and initialize dateRange plugin
    this.initialDate = new Date().toISOString().slice(0, 10);
    if (this.myDateInit) {
      let begin: Date = new Date();
      this.model = {
        isRange: false, 
        singleDate: {
          date: {
            year: begin.getFullYear(), month: begin.getMonth() + 1, day: begin.getDate()
          }
        }
      };
    }

    // Initialize default 'clicked' options for chart button options
    this.isActive = [false, false, false, false];
    this.chartActive = [true, false, false, false];

    // Get all assets (according to user's assigned organizations)
    let plants = this.plantsService.getAllAssets().subscribe(res => {
      this.listAssets = res["data"]["assets"];
      
      // Default values for chart 
      this.view = "month";
      if (this.organizationId == undefined){
        this.organizationId = this.listAssets[0].id;
      }
      this.chart1Type = "bar";

      // Initialize a draw chart according to the default values
      this.onMeasureClickRange(this.view, this.initialDate);

      // Api call to get the energy summary stats of all assets in the organization
      let energy_produced = this.logsService.getEnergySummaryByAsset(this.organizationId).subscribe(resp => {
        this.eProduced = resp["data"]["energy"];//results[1];
        this.energyDay = this.eProduced.today.total_energy_kWh || 0;
        this.energyWeek = this.eProduced.thisWeek.total_energy_kWh > 0 ? (this.eProduced.thisWeek.total_energy_kWh/1000).toFixed(2) : this.eProduced.thisWeek.total_energy_kWh || 0
        this.energyMonth = this.eProduced.thisMonth.total_energy_kWh > 0 ? (this.eProduced.thisMonth.total_energy_kWh/1000).toFixed(2) : this.eProduced.thisMonth.total_energy_kWh || 0
        this.energyYear = this.eProduced.lifeTime.total_energy_kWh > 0 ? (this.eProduced.lifeTime.total_energy_kWh/1000).toFixed(2) : this.eProduced.lifeTime.total_energy_kWh || 0
      });

      this.logsService.getAssetEnviromentalStats(this.organizationId).subscribe(resp => {
        this.environment = resp["data"]["environmentals"];
        console.log(this.environment);
        this.environmentCO2 = this.environment.avoided_kg_of_co2.toFixed(2); 
        this.environmentHouse = this.environment.number_of_homes.toFixed(0);
        this.environmentFuel = this.environment.number_of_crude_barrels.toFixed(2);
      });


    }, (err) => {
      Swal.fire({
        type: 'error',
        title: 'Error en el servidor',
        text: "No su pudo obtener la informacion"
      });
    });

    //this.chartjs = true;
    setTimeout(()=>{
      Swal.close();
    }, 2700);
  }
 
  // Default check asset dropdown if a value is equal to an assetID
  isSelected(){
    if(this.organizationId!=undefined){
      return true;
    }
    else{
      return false;
    }
  }

  ngOnChanges() {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    //this.dtTrigger.next();
  }

  // Trigger again the chart with the selected assetID
  onChangeObj(event:any) {
    this.organizationId = event.target.value;
    this.onMeasureClickRange(this.view, this.initialDate, this.organizationId);
  }
  
  // Change the date range of the chart, according to the selected view (daily, weekly, ...)
  onDateChanged(event: IMyDateModel) {
    let endDate = `${event.singleDate.date.year}-${event.singleDate.date.month}-${event.singleDate.date.day}`;
    this.initialDate  = endDate;
    switch (this.view)
    { 
      case "day": 
        this.onMeasureClickRange(this.view, endDate);
        break; 
      case "week": 
        this.onMeasureClickRange(this.view, endDate);
        break; 
      case "month": 
        this.onMeasureClickRange(this.view, endDate);
        break; 
      case "year":
        this.onMeasureClickRange(this.view, endDate);
        break;
      default: 
        console.log("nada");
    } 
  }

  // Draw a measure chart using chartjs, given some params, view, for daily, weekly, monthly or yearly measures;
  // measureDate, for a date range given a view and a paramID, for an specific assetID selected in the dropdown  
  onMeasureClickRange(view:string, measureDate?:string, paramId?:string): void {
    if(this.initialLoad == false){
      Swal.fire({
        allowOutsideClick: false,
        type: 'info',
        text: 'Espere por favor...'
      });
      Swal.showLoading();
    }
    this.initialLoad = false;
    this.view = view;

    // Chart (re)initialize, to prevent double load on changing date range or views
    if (this.chart1 != undefined){
      this.chart1.destroy();
    }
    this.chart1 = undefined;
    
    let dateRange:string;
    if (measureDate === undefined){
      dateRange = this.initialDate;
    }
    else {
      dateRange = measureDate;
    }

    // Set default assetID if paramId doesn't come in the function call
    let assetId:string;
    if (paramId === undefined){
      assetId = this.listAssets[0]["id"]; // Grab the first object
    }
    else {
      assetId = paramId;
    }
    
    // Select an interval according to the API permitted param
    let interval:string;
    switch (view)
    { 
      case "day": 
        interval = "1D";
        this.isActive = [true, false, false, false];
        break; 
      case "week": 
        interval = "7D";
        this.isActive = [false, true, false, false];
        break; 
      case "month":
        interval = "1M";
        this.isActive = [false, false, true, false];
        break; 
      case "mtd": //TO DO
        interval = "MTD";
        break;
      case "year":
        interval = "YTD";
        this.isActive = [false, false, false, true];
        break;
      default: 
    }

    // Get the measures according to the meters, given the params required
    this.logsService.getEnergyProducedByParams(assetId,interval,dateRange).toPromise()
    .then((data: any) => {
      this.metersData = [];      
      this.metersKeys = Object.keys(data["data"]["dataset"]);
      
      // Get all the values according to each index (meter) 
      this.metersValues = Object.values(data["data"]["dataset"]);

      /// Get the keys of those values
      let meterKeys2 = Object.keys(this.metersValues);
      this.displayedColumns= [];
      this.tableData = [];

      // The chart data object requires certain ordered params, so we itirate the returned object from the API call,
      // and build the new object with the required/needed values
      for (let prop in meterKeys2) { 
        //let label = localStorage.getItem("email") == "inverlec@grupomerelec.com" ? `INVERLEC ${prop}` : this.metersValues[prop]["label"];
        let label = this.metersValues[prop]["label"];
        let measure_values = Object.values(this.metersValues[prop]["data"].map(obj => obj.total_energy_kWh).reverse())
        this.metersData.push({"label": label, backgroundColor: this.barChartColors[prop], data: measure_values, borderColor: this.borderChartColors[prop] });
        this.tableData.push({headers: label+" kWh Generado", dataValues: measure_values})
      }

      // Initialization of arrays for the table view of the measure values
      this.array1 = this.array2 = this.array3 = [];

      // Loop to build an object that contains the date and each meter value from a certain asset
      // This object is required to build the datatable
      for (let prop in meterKeys2) { 
        this.array2 = [];
        //let label = localStorage.getItem("email") == "inverlec@grupomerelec.com" ? `INVERLEC ${prop}` : this.metersValues[prop]["label"];
        let quantity = Object.keys(this.metersValues[0]["data"]);
        let mvalues = Object.values(this.metersValues[prop]["data"].map(obj => obj).reverse())
        
        for (let prop2 in quantity){
          // Date insertion
          this.array3 = [];
          let columnname = `medidor${prop}`;
         
          if (+prop == 0 && mvalues[prop2] != undefined){
            let dateT = this.getDateWithFormat(this.view, mvalues[prop2]["dateMax"])
            this.array3.push(dateT);
          }
          
          if (mvalues[prop2] != undefined) { 
            this.array3.push(mvalues[prop2]["total_energy_kWh"]);
          }
          else {
            this.array3.push(0)
          }

          if (+prop == 0){
            this.array2.push(this.array3)
          }
          
          if (+prop != 0) {
            this.array1[prop2].push(this.array3[0]);
          }
        }
        if (+prop == 0){
          this.array1 = (this.array2)
          //this.array1 = [].concat.apply([], this.array1)
        }    
      }

      // According to the selected interval in the option buttons of the chart, the date is given an specific format 
      switch (view){
        case "day": 
          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'HH:mm ','es-Es','-0600')).reverse();
          break; 
        case 'week':
          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'EEEE dd','es-Es','-0600')).reverse();
          break;
        case "year":
          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'MM/yyyy','es-Es','-0600')).reverse();
          break;
        default: 
          this.barChartLabels = this.metersValues[0]["data"].map(obj => formatDate(obj.dateMax, 'dd/MM','es-Es','-0600')).reverse(); 
      }

      // Push the values to the chart object
      this.tableData.push({headers: "Fecha/Hora", dataValues: this.barChartLabels})
      this.tableData.reverse()
      for( let v in Object.keys(this.tableData)){
        this.displayedColumns.push(this.tableData[v]["headers"]);
      }
      this.tableData2 = this.array1;

      this.dataSource.data = this.tableData2;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;

      this.showTable = true;
      this.chart1 = new Chart('canvas', {
        type: this.chart1Type,
        options: {
          title: {
            display: true,
          },
          tooltips: {
            mode: 'index',
            callbacks: {
              // Get the total of the energy produced in every point and show it in the hover tooltip
              label: function (tooltipItem, data) { 
                var label = data.datasets[tooltipItem.datasetIndex].label || '';
                var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
                var total = 0;

                for (var i = 0; i < data.datasets.length; i++)
                  total += +data.datasets[i].data[tooltipItem.index];

                if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
                  return label + " : " + value;
                }
                else {
                  return [label + " : " + value, "TOTAL : " + Math.round(total)];
                }
              }
            }         
          },
          responsive: true,
          maintainAspectRatio: false,
          scales: {
            xAxes: [{
              stacked: true,
              barPercentage: 0.7
            }],
            yAxes: [{
              stacked: true
            }]
          }
        },
        data: {
          labels: this.barChartLabels,
          datasets: this.metersData,
        }, 
      });
      this.chartjs = true;
    });
    setTimeout(()=>{
      Swal.close();
    }, 1500)
  }

  getDateWithFormat(view:string, date:string){
    let dateT;
    switch (view){
      case "day": 
        dateT = formatDate(date, 'HH:mm','es-Es','-0600');
        break; 
      case 'week':
        dateT = formatDate(date, 'EEEE dd','es-Es','-0600');
        break;
      case "year":
        dateT = formatDate(date, 'MM/yyyy','es-Es','-0600');
        break;
      default: 
        dateT = formatDate(date, 'dd/MM','es-Es','-0600');
    }
    return dateT;
  }

  // Change visualization type to table view
  changeToTable(){
    let table = document.getElementById("toogleTable");
    let chart = document.getElementById("chart-wrapper");
    this.chartActive = [false, false, false, true];
    chart.style.display = "none";
    table.style.display = "block";
  }

  // Print the table values, according to the generated information
  printTable(){
    printJS(
      { printable: 'measuresTable', type: 'html', 
        header: '<h3 class="report-header">Datos de la planta </h3>',
        documentTitle: 'DENMARK - Informacion generada',
        style: '.report-header{ color: #075D9D; font-size: 24px; }' }
    );
  }

  // Function for change the chart type without reloading its values
  changeGraphicType(chartType:string){
    let table = document.getElementById("toogleTable");
    let chart = document.getElementById("chart-wrapper");
    chart.style.display = "block";
    table.style.display = "none";
    // Select an interval according to the API permitted param
    let chartT:string;
    switch (chartType)
    { 
      case "bar": 
        this.chartActive = [true, false, false, false];
        break; 
      case "line": 
        this.chartActive = [false, true, false, false];
        break; 
      case "radar":
        this.chartActive = [false, false, true, false];
        break; 
      default: 
    }  

    this.chart1Type = chartType;

    if (this.chart1 != undefined){
      this.chart1.destroy();
    }
    this.chart1 = undefined;
    this.chart1 = new Chart('canvas', {
      type: this.chart1Type,

      options: {
        title: {
          display: true,
        },
        tooltips: {
          mode: 'index',
          callbacks: {
            // Get the total of the energy produced in every point and show it in the hover tooltip
            label: function (tooltipItem, data) { 
              var label = data.datasets[tooltipItem.datasetIndex].label || '';
              var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
              var total = 0;

              for (var i = 0; i < data.datasets.length; i++)
                total += +data.datasets[i].data[tooltipItem.index];

              if (tooltipItem.datasetIndex !== data.datasets.length - 1) {
                return label + " : " + value;
              }
              else {
                return [label + " : " + value, "TOTAL : " + Math.round(total)];
              }
            }
          }         
        },
        responsive: true,
        maintainAspectRatio: false,
        scales: {
          xAxes: [{
            stacked: true,
            barPercentage: 0.7
          }],
          yAxes: [{
            stacked: true
          }]
        }
      },
      data: {
        labels: this.barChartLabels,
        datasets: this.metersData,
      }, 
    });
  }

}
