// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import dom from "./dom.js";
import scales from "./scales.js";
import state from "./state.js";
import url from "./url.js";

var chart = null;
var dataProvider = null;

function getBenchmarkColors(theChart) {
  const benchmarkColors = {};
  for (var datasetIndex = 0;
      datasetIndex < theChart.data.datasets.length;
      datasetIndex++) {
    if (theChart.getDatasetMeta(datasetIndex).hidden) {
      continue;
    }
    const dataset = theChart.data.datasets[datasetIndex];
    const benchmark = dataset.benchmark;
    const benchmarkColor = dataset.borderColor;
    if (!(benchmark in benchmarkColors)) {
      benchmarkColors[benchmark] = benchmarkColor;
    }
  }
  return benchmarkColors;
}

function get() {
  return chart;
}

function getData() {
  const filteredCommits = state.commits(state.zoom);
  return dataProvider(filteredCommits);
}

function getDataLabelFormatter(value, context) {
  var percentageChange = getDataPercentageChange(context);
  var percentageChangeTwoDecimals = Math.round(percentageChange * 100) / 100;
  var glyph = percentageChange < 0 ? '▼' : '▲';
  return glyph + ' ' + percentageChangeTwoDecimals + '%';
}

function getDataPercentageChange(context) {
  var i = context.dataIndex;
  var value = context.dataset.data[i];
  var j = i;
  var previousValue;
  do {
    if (j == 0) {
      return null;
    }
    previousValue = context.dataset.data[--j];
  } while (previousValue === undefined || isNaN(previousValue));
  return (value - previousValue) / previousValue * 100;
}

function initializeChart(options) {
  chart = new Chart(dom.canvas, {
    data: getData(),
    options: options,
    plugins: [ChartDataLabels]
  });
  // Hide disabled legends.
  if (state.selectedLegends.size < state.legends.size) {
    update(false, true);
  } else {
    update(false, false);
  }
  document.addEventListener('keydown', e => {
    state.handleKeyDownEvent(e, () => update(true, false));
  });
}

function setDataProvider(theDataProvider) {
 dataProvider = theDataProvider;
}

function update(dataChanged, legendsChanged) {
  console.assert(state.zoom.left <= state.zoom.right);

  // Update datasets.
  if (dataChanged) {
    const newData = getData();
    Object.assign(chart.data, newData);
    // Update chart.
    chart.update();
  }

  // Update legends.
  if (legendsChanged || (dataChanged && state.selectedLegends.size < state.legends.size)) {
    for (var datasetIndex = 0;
        datasetIndex < chart.data.datasets.length;
        datasetIndex++) {
      const datasetMeta = chart.getDatasetMeta(datasetIndex);
      datasetMeta.hidden = !state.isLegendSelected(datasetMeta.label);
    }

    // Update scales.
    scales.update(chart.options.scales);

    // Update chart.
    chart.update();
  }

  dom.updateBenchmarkColors(getBenchmarkColors(chart));
  dom.updateChartNavigation();
  url.updateHash(state);
}

export default {
  get: get,
  getDataLabelFormatter: getDataLabelFormatter,
  getDataPercentageChange: getDataPercentageChange,
  initializeChart: initializeChart,
  setDataProvider: setDataProvider,
  update: update
};
