import { Directive, OnInit, OnDestroy, OnChanges, SimpleChanges, EventEmitter,ElementRef, Input, Output } from '@angular/core';
import { Chart } from 'chart.js';

import { BBCustomChartService } from './bb-custom-chart.service';

@Directive({
  selector: 'canvas[bb-chart]',
  exportAs: 'bb-chart'
})
export class BBCustomChartDirective implements OnDestroy, OnChanges, OnInit {

  private _chart: any;
  private _chartCanvas: any;
  private _chartContext: any;
  private initFlag: boolean = false;

  @Input() public chartType: string | any; //It can be bar, horizontalBar, pie, doughnut etc.
  @Input() public legend: boolean | any;

  // @Input() public data: number[] | any[]; // For chartType pie and doughnut
  // @Input() public datasets: any[]; // For chartType bar, horizontalBar etc. (other than pie and doughnut)
  @Input() public data: number[] | any; // For chartType pie and doughnut
  @Input() public datasets: any; // For chartType bar, horizontalBar etc. (other than pie and doughnut)
  @Input() public labels: Array<any> = [];
  @Input() public colors: Array<any> | any;

  @Input() public options: any = {};
  @Input() public chartHeight: any;

//Added by Pramod S on 16-APR-21 for click on bar chart [START]
 @Output() public chartClick:EventEmitter<any> = new EventEmitter();
 @Output() public chartHover:EventEmitter<any> = new EventEmitter();
 @Output() onDrillDown: EventEmitter<any> = new EventEmitter();
 //Added by Pramod S on 16-APR-21 for click on bar chart [END]

  constructor(private _chartElem: ElementRef, private _chartSvc: BBCustomChartService) { }

  ngOnInit() {

    console.log("BB Custom CHart ::::::", this.datasets);
     console.log("BB Custom CHartthis.options", this.options);
    this._chartCanvas = this._chartElem.nativeElement;
    this._chartContext = this._chartElem.nativeElement.getContext('2d');
    this.initFlag = true;
    if(this.chartHeight)
    {
      this.options.height = this.chartHeight;
      console.log("Setting dynamic Height...", this.chartHeight);
    }
    if (this.data || this.datasets) {
      this.refreshChart();
      this._chartCanvas.height = this.options.height;
      console.log("this.options.widthinpercentage...", this.options.widthinpercentage);
      if (this.options.widthinpercentage ==='true')
      {
          this._chartCanvas.style.width = this.options.width + "%";
      }
      else
      {
      this._chartCanvas.width = this.options.width;
    }
  }
  }

  ngOnChanges(changes: SimpleChanges) {

    if (this.initFlag) {
      console.log('BBCustomChartDirective.ngOnChanges changes ::', changes);
      // Check if the changes are in the data or datasets
      if (changes.hasOwnProperty('data') || changes.hasOwnProperty('datasets')) {
        if (changes['data']) {
          this.updateChartData(changes['data'].currentValue);
        }
        else {
          this.updateChartData(changes['datasets'].currentValue);
        }
        this._chart.update();
      }
      else {
        // otherwise rebuild the chart
        this.refreshChart();
      }
    }
  }

  ngOnDestroy() {
    if (this._chart) {
      this._chart.destroy();
      this._chart = void 0;
    }
  }

  private updateChartData(newDataValues: number[] | any[]): void {
    if (Array.isArray(newDataValues[0].data)) {
      this._chart.data.datasets.forEach((dataset: any, i: number) => {
        dataset.data = newDataValues[i].data;

        if (newDataValues[i].label) {
          dataset.label = newDataValues[i].label;
        }
      });
    } else {
      this._chart.data.datasets[0].data = newDataValues;
    }
  }

  private refreshChart() {
    this.ngOnDestroy();
    console.log("BBCustomChartDirective.refreshChart :");

    var datasets = this.initDatasets();
    var data = {
      labels: this.labels,
      datasets: datasets
    }
    var options = this.initOptions();
    var plugins = this._chartSvc.getPlugins(this.chartType, this.options, this);
    this._chart = this._chartSvc.initChart(this.chartType, this._chartContext, data, options, plugins);
    console.log("BBCustomChartDirective Initialisation of _chart ::", this._chart, " data ::", data, " options ::", this.options, " plugins ::", plugins);
    console.log("BBCustomChartDirective.this.options.width:",this.options.width);
    if (this.options) {
      this._chart.canvas.parentNode.style.height = this.options.height + "px";
     console.log("this.options.widthinpercentage:",this.options.widthinpercentage);
       if (this.options.widthinpercentage ==='true')
      {
           this._chart.canvas.parentNode.style.width = this.options.width + "%";
      }
      else
      {
        this._chart.canvas.parentNode.style.width = this.options.width + "px";
     }
    } 
  }

  private initDatasets(): any {

    let datasets: any = void 0;
    console.log("*********",this.datasets);
    console.log("********* this.data ",this.data);

    // in case if datasets is not provided, but data is present
    if (!this.datasets || !this.datasets.length && (this.data && this.data.length)) {
      if (Array.isArray(this.data[0])) {
        datasets = (this.data as Array<number[]>).map((data: number[], index: number) => {
          return { data, label: this.labels[index] || `Label ${index}` };
        });
      } else {
        datasets = [{ data: this.data, label: this.labels }];
      }
    }

    if ( (this.datasets && this.datasets.length) || (datasets && datasets.length) ) {
      datasets = (this.datasets || datasets).map((elm: number, index: number) => {
          let newElm: any = Object.assign({}, elm);

          if (this.datasets) {
            if (this.datasets[index].backgroundColor) {
              //backgroundColor
              Object.assign(newElm, this.datasets[index].backgroundColor[index]);
            }
            else if (this.datasets[index].backgroundGradient) {
                //backgroundColor
                var backgroundGradient = this.datasets[index].backgroundGradient;
                var gradient = this._chartSvc.getGradient(this._chartContext, backgroundGradient);
                console.log('initDatasets gradient ::[',index,']', newElm, gradient);
                Object.assign(newElm, gradient);
            }
            else {
              //default
              Object.assign(newElm, this._chartSvc.getColors(this.chartType, index, newElm.data.length, this.options.opacity || 1 ));
            }
          }
          else if(this.options.condnFormat && this.chartType==='doughnut')
          {
            var conditions = this.options.condnFormat;
            var condnColors = this._chartSvc.evaluateConditionalColor(newElm.data, conditions);
            console.log('Conditional Colors Exist', newElm, condnColors);
            Object.assign(newElm, this._chartSvc.formatPieColors(condnColors, this.options.opacity || 1 , this.options.borderWidth, this.options.borderColor));
          }
          else if ( this.colors && this.colors.length && ( this.chartType==='pie' || this.chartType==='doughnut' ) )  {
            //Object.assign(newElm, this.colors[index]);
            console.log('Custom Colors Exist', this.colors);
            Object.assign(newElm, this._chartSvc.formatPieColors(this.colors, this.options.opacity || 1 , this.options.borderWidth, this.options.borderColor));
          } else {
            Object.assign(newElm, this._chartSvc.getColors(this.chartType, index, newElm.data.length, this.options.opacity || 1 ));
          }
          return newElm;
        });
    }

    if (!datasets) {
      throw new Error(`ng-charts configuration error,
            data or datasets field are required to render char ${this.chartType}`);
    }
    console.log("dataset which is going to be return ", datasets);

    return datasets;
  }

  private initOptions() {
    var self =this; //Added by Pramod S on 16-APR-21 for click on bar chart
    var options: any = {};
    /* Added By Vikas lagad on 25-June-2020[changes to set legend position for pie & doughnut chart]Start*/ 
    console.log("BBCustomChartDirective.refreshChart  this.options:",this.options);

    if (this.options) {
      options.legend = {
        display: this.options.legend,
        position : this.options.position || 'top'
      };
      options.segmentShowStroke =  this.options.segmentShowStroke || false;
      options.borderWidth = 2;
      /* Added By Vikas lagad  on 25-June-2020[changes to set legend position for pie & doughnut chart]End*/ 
      options.cutoutPercentage = this.options.cutOutPercentage || 0;
      options.animation = {
        animateScale: this.options.animateScale,
        animateRotate: this.options.animateRotate
      };

      options.responsive = this.options.responsive;
      options.maintainAspectRatio = this.options.maintainAspectRatio;
      options.onClick=this.options.onClick; //Added by Pramod S on 16-APR-21 for click on bar chart

      if(this.options.tooltips)
      {
          options.tooltips = this.options.tooltips;
      }
      else
      {
          options.tooltips = {
            enabled: this.options.tooltip
          };
          if( !this.options.tooltip )
          {
            options.hover = {
              mode: null
            };
          }
      }
      
      if(this.options.scales)
      {
          options['scales'] = this.options.scales;
      }
      //TODO : for onHover and onClick events
      //Added by Pramod S on 16-APR-21 for click on bar chart [START]
      options.hover = options.hover || {};
      if (!options.hover.onHover) {
        options.hover.onHover = (active: Array<any>) => {
          if (active && !active.length) {
            return;
          }
          this.chartHover.emit({ active });
        };  
      }
      
      if (!options.onClick) 
      {
        if(this.options.drilldown == 'true')
        {    
            options.onClick = (event: any, active: Array<any>) => 
            {
                //this.chartClick.emit({ event, active });'
                console.log("self [",self ,"]this--[",this,"]");
                //self.onBarClick();
                console.log("this._chart ::",this._chart);
                
                active =this._chart.getElementAtEvent(event);
                console.log("active ::",active[0]);

                if(active.length > 0)
                {
                    var label =active[0]._view.label;
                    console.log("label ::[",label,"]");
                    var lowervalue = label.toLowerCase( );
                    lowervalue = lowervalue.trim();
                    var linkMetaData = lowervalue.replace(' ','_');
                    console.log("lowervalue::[",lowervalue,"]");
                    console.log("linkMetaData == [",linkMetaData,"]");

                    console.log("ondrilldown--",this.onDrillDown);
                    var obj= {
                            "LINK_METADATA":linkMetaData,
                             "DESCR": label.trim(),
                            };
                            this.onDrillDown.emit(obj);
                }
            };
         }
      }
      console.log("end if optionss[",JSON.stringify(options),"],end if this.options[",JSON.stringify(this.options),"]");
      //Added by Pramod S on 16-APR-21 for click on bar chart [END]
      //TODO : for customlegend and customlabel
      /*
      if (this.customLabels && this.customLegend) {
  
        options.legendCallback = this.getLegands,
          options.tooltips = {
            callbacks: {
              // label: this.getValue
            }
          }
      }
      */
    }
    return options; 
  }



  /* 
  
  getValue(tooltipItem, data){
    var dataset = data.datasets[tooltipItem.datasetIndex];
    var index = tooltipItem.index;
    return dataset.labels[index] + ': ' + dataset.data[index];
  } 
   
  */


  /*

  getLegands(chart) {
    var text = [];
    var helper = {};
    helper['onClick'] = function (dsIdx, dataIndex) {
      var meta = chart.getDatasetMeta(dsIdx);
      if (chart.config.type == "pie" || chart.config.type == "doughnut") {
        meta.data[dataIndex].hidden = meta.data[dataIndex].hidden === false ? true : false;
      }
      if (chart.config.type == "bar" || chart.config.type == "horizontalBar") {
        meta.hidden = meta.hidden === null ? !chart.data.datasets[dataIndex].hidden : null;
      }
      chart.update();
    };
    window['customLegendHelper'] = helper;
    if (chart.config.type == "pie" || chart.config.type == "doughnut") {
      var dsi = 0;
      for (var dataSet of chart.data.datasets) {
        var customLegands = [];
        var i = 0;
        for (var data of dataSet.data) {
          var customLegand = { label: dataSet.label[i], color: dataSet.backgroundColor[i] };
          if (!containsObject(customLegand, customLegands)) {
            customLegands.push(customLegand);
          }
          i++;
        }

        text.push(`<ul class="custom-legends  ${chart.id}-legend">`);
        for (var k = 0; k < customLegands.length; k++) {
          if (customLegands.length == 1) {
            text.push(`<li style = "padding-left: 137px; ">
                                  <span  class="legend" 
                                          onclick="customLegendHelper.onClick(${dsi}, ${k});" 
                                          style="background-color: ${ customLegands[k].color}">
                                  </span>
                                  <span style = "padding-left: 12px; ">${customLegands[k].label}</span>
                                  </li>`);
          }
          else {
            text.push(`<li style = "">
                                  <span  class="legend" 
                                          onclick="customLegendHelper.onClick(${dsi}, ${k});" 
                                          style="background-color: ${ customLegands[k].color}">
                                  </span>
                                  <span style = "padding-left: 12px; ">${customLegands[k].label}</span>
                                  </li>`);
          }
        }
        text.push(`</ul>`);
        dsi++;
      }
      return text.join("");
    }
    if (chart.config.type == "bar" || chart.config.type == "horizontalBar") {
      var t = 0;
      for (var dataSet of chart.data.datasets) {
        var customLegands = [];
        var customLegand = { label: dataSet.label, color: dataSet.backgroundColor };

        if (!containsObject(customLegand, customLegands)) {
          customLegands.push(customLegand);
        }
        text.push(``);
        for (var k = 0; k < customLegands.length; k++) {
          text.push(`  
                    <span  class="legend-color" 
                            onclick="customLegendHelper.onClick(${t}, ${k});" 
                            style="background-color: ${ customLegands[k].color}">
                    </span>
                    <span class = "legend-text">${customLegands[k].label}</span>
                  `);
        }
        text.push(``);
        t++;
      }
      return text.join("");
    }
  }
  */
}
