import { Component, h, Host, Prop } from '@stencil/core';
import { ArcElement, BarController, BarElement, BubbleController, CategoryScale, Chart, Decimation, DoughnutController, Filler, Legend, LinearScale, LineController, LineElement, LogarithmicScale, PieController, PointElement, PolarAreaController, RadarController, RadialLinearScale, ScatterController, TimeScale, TimeSeriesScale, Title, Tooltip, } from "chart.js";
import CalendarUtils from "@dvn/core/util/calendar";
Chart.register(ArcElement, LineElement, BarElement, PointElement, BarController, BubbleController, DoughnutController, LineController, PieController, PolarAreaController, RadarController, ScatterController, CategoryScale, LinearScale, LogarithmicScale, RadialLinearScale, TimeScale, TimeSeriesScale, Decimation, Filler, Legend, Title, Tooltip);
const colors = [
  '#1abc9c',
  '#9b59b6',
  '#3498db',
  '#e74c3c',
  '#2ecc71',
  '#e67e22',
  // '#34495e',
  '#f1c40f',
  // '#ecf0f1',
  '#95a5a6',
  '#2980b9',
  '#16a085',
  '#c0392b',
  '#8e44ad',
  '#e84393',
  '#f39c12',
  '#27ae60',
  // '#2c3e50',
  // '#d35400',
  // '#bdc3c7',
  '#7f8c8d',
];
export class DamgaProxyGraph {
  constructor() {
    this.valueType = 'basic';
    this.graphViewType = 'line';
  }
  componentDidRender() {
    if (!this.isPending) {
      this.renderGraph();
    }
  }
  renderGraph() {
    var _a;
    const { data, dateFormat, domains, graphOptions, graphViewType, valueKey, valueType } = this;
    const ctx = document.getElementById(valueKey).getContext('2d');
    (_a = this.canvas) === null || _a === void 0 ? void 0 : _a.destroy();
    getGraphConfigByType(valueKey, valueType, graphViewType, graphOptions, dateFormat, domains, data).then(graphConfig => {
      this.canvas = new Chart(ctx, graphConfig);
    });
  }
  render() {
    const { valueKey } = this;
    const height = '400';
    return (h(Host, { class: "d-block", style: { height: `${height}px` } },
      h("canvas", { id: valueKey, width: height, height: height })));
  }
  static get is() { return "damga-proxy-graph"; }
  static get properties() { return {
    "data": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "GraphData",
        "resolved": "{ [key: string]: any; timeIntervals: string[]; }",
        "references": {
          "GraphData": {
            "location": "global"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "dateFormat": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "date-format",
      "reflect": false
    },
    "valueKey": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "value-key",
      "reflect": false
    },
    "valueType": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "ValueType",
        "resolved": "\"basic\" | \"object\"",
        "references": {
          "ValueType": {
            "location": "global"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "value-type",
      "reflect": false,
      "defaultValue": "'basic'"
    },
    "graphViewType": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "ChartType",
        "resolved": "\"bar\" | \"bubble\" | \"doughnut\" | \"line\" | \"pie\" | \"polarArea\" | \"radar\" | \"scatter\"",
        "references": {
          "ChartType": {
            "location": "import",
            "path": "chart.js"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "graph-view-type",
      "reflect": false,
      "defaultValue": "'line'"
    },
    "graphOptions": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "GraphOptions",
        "resolved": "{ x: { stacked: boolean; }; y: { stacked: boolean; }; }",
        "references": {
          "GraphOptions": {
            "location": "global"
          }
        }
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "isPending": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      },
      "attribute": "is-pending",
      "reflect": false
    },
    "domains": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "string[]",
        "resolved": "string[]",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": ""
      }
    }
  }; }
}
async function getGraphConfigByType(valueKey, valueType, graphViewType, graphOptions, dateFormat, domains, data) {
  var _a, _b;
  let datasets = [];
  if (valueType === 'object' && domains.length === 1) {
    // get the first domain. multiple domains cannot be supported
    const values = data[domains[0]];
    // find the unique keys that exist in all analyses
    const dataByKeys = {};
    values.forEach((analysesForDomain) => Object.keys(analysesForDomain[valueKey] || {}).forEach(key => {
      dataByKeys[key] = [];
    }));
    // separate the values by keys
    values.forEach((analysesForDomain) => {
      Object.keys(dataByKeys).forEach((subValueKey) => {
        var _a, _b;
        if (dataByKeys[subValueKey]) {
          dataByKeys[subValueKey].push((_a = analysesForDomain[valueKey]) === null || _a === void 0 ? void 0 : _a[subValueKey]);
        }
        else {
          dataByKeys[subValueKey] = [(_b = analysesForDomain[valueKey]) === null || _b === void 0 ? void 0 : _b[subValueKey]];
        }
      });
    });
    datasets = Object.keys(dataByKeys).map((key) => {
      const color = colors[Math.abs(hash(key)) % colors.length];
      return {
        data: dataByKeys[key],
        label: key || 'UNKNOWN',
        fill: false,
        borderColor: color,
        backgroundColor: color,
        tension: 0.2,
        pointRadius: 2
      };
    });
  }
  else {
    datasets = Object.entries(data)
      .filter(([domain]) => domain != 'timeIntervals')
      .map(([domain, analysesForDomain]) => {
      const color = colors[Math.abs(hash(domain)) % colors.length];
      return {
        data: analysesForDomain.map(analysis => analysis[valueKey]),
        label: domain,
        fill: false,
        borderColor: color,
        backgroundColor: color,
        tension: 0.2,
        pointRadius: 2
      };
    });
  }
  return {
    type: graphViewType,
    data: {
      labels: data.timeIntervals.map(dateString => {
        return CalendarUtils.format(new Date(dateString), dateFormat);
      }),
      datasets,
    },
    options: {
      scales: {
        x: {
          stacked: (_a = graphOptions === null || graphOptions === void 0 ? void 0 : graphOptions.x) === null || _a === void 0 ? void 0 : _a.stacked,
        },
        y: {
          beginAtZero: true,
          stacked: (_b = graphOptions === null || graphOptions === void 0 ? void 0 : graphOptions.y) === null || _b === void 0 ? void 0 : _b.stacked,
        }
      },
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: {
          display: true,
          position: 'left',
          labels: {
            boxWidth: 12
          }
        }
      }
    },
  };
}
function hash(str) {
  var hash = 0, i, chr;
  if (str.length === 0)
    return hash;
  for (i = 0; i < str.length; i++) {
    chr = str.charCodeAt(i);
    hash = ((hash << 5) - hash) + chr;
    hash |= 0; // Convert to 32bit integer
  }
  return hash;
}
