import {Font} from "../../../generated/ru/micord/ervu_dashboard/model/Font";
import {Chart, ChartData} from "chart.js";

export class ChartUtils {

  public static isEmpty(chart: Chart): boolean {
    return chart.data.datasets
               .map(dataset => dataset.data.length)
               .reduce((x, y) => x + y, 0) === 0 ||
           this.hasNotData(chart.data);
  }

  public static hasNotData(data: ChartData): boolean {
    return data.datasets
               .map(dataset => dataset.data)
               .reduce((acc, data) => acc.concat(data), [])
               .filter(dataPoint => dataPoint.y !== null && dataPoint.y !== '').length === 0;
  }

  public static getTextMetrics(ctx: CanvasRenderingContext2D, text: string, font: Font) {
    ctx.font = this.getFont(font);
    let textMetrics = ctx.measureText(text);
    return {
      height: textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent,
      width: textMetrics.width
    }
  }

  public static getFont(font: Font): string {
    return [font.weight, `${font.size}px`, font.family]
        .filter(elem => elem)
        .join(' ');
  }

  public static clone<T>(source: T): T {
    return JSON.parse(JSON.stringify(source));
  }

  public static hexToHsl(colorHex: string, lightness?: number): string {
    if (!colorHex) {
      return colorHex;
    }
    let result: string[] = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(colorHex);
    if (!result) {
      result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(colorHex);
    }
    if (!result || (result.length != 4 && result.length != 5)) {
      return undefined;
    }

    let r = parseInt(result[1], 16);
    let g = parseInt(result[2], 16);
    let b = parseInt(result[3], 16);
    r /= 255;
    g /= 255;
    b /= 255;

    const max = Math.max(r, g, b), min = Math.min(r, g, b);
    let h, s, l = (max + min) / 2;

    if (max == min) {
      h = s = 0; // achromatic
    }
    else {
      const d = max - min;
      s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
      switch (max) {
        case r:
          h = (g - b) / d + (g < b ? 6 : 0);
          break;
        case g:
          h = (b - r) / d + 2;
          break;
        case b:
          h = (r - g) / d + 4;
          break;
      }
      h /= 6;
    }

    h = Math.round(h * 360);
    s = Math.round(s * 100);
    l = Math.round(l * 100);

    if (lightness) {
      l *= lightness / 100;
      l = Math.round(Math.max(0, Math.min(100, l)));
    }

    let a: number;
    if (result.length == 5) {
      a = parseInt(result[4], 16)
      a = Math.round(a / 255 * 10) / 10;
    }

    return result.length == 5
           ? 'hsla(' + h + ', ' + s + '%, ' + l + '%, ' + a + ')'
           : 'hsl(' + h + ', ' + s + '%, ' + l + '%)';
  }
}
