const selectors = {
  get sortControl() {
    return document.forms.sortControl.elements;
  },
  get clusterControl() {
    return document.forms.clusterControl.elements;
  },
  get colorSpace() {
    return selectors.colorSpace.value;
  },
};

const onMetricChange = (elements) => {
  elements.sortOrderLabel.value = elements.sortOrder.checked
    ? "Maximizing"
    : "Minimizing";
  const kind = elements.metricKind.value;
  elements.whole.disabled = kind !== "whole";
  elements.mean.disabled = kind !== "mean";
  elements.statistic.disabled = kind !== "statistic";
  elements.sortMetric.value = elements[kind].value;

  updateSort();
  showResults(selectors.sortControl.resultsToDisplay.value);
};

const onColorChange = (inputValue) => {
  console.log(inputValue);
  const colorInput = "#" + (inputValue?.replace("#", "") ?? "FFFFFF");

  if (colorInput.length !== 7) {
    return;
  }

  const rgb = d3.color(colorInput);
  if (!rgb) {
    return;
  }

  const refomatted = rgb.formatHex();
  selectors.sortControl.colorText.value = refomatted;
  selectors.sortControl.colorPicker.value = refomatted;

  // TODO last color saver
  // TODO bg + text color change

  updateScores(rgb);
  updateSort();
  showResults(selectors.sortControl.resultsToDisplay.value);
};

const calcScores = (data, target) => {
  const sigma = Math.sqrt(
    data.inertia - 2 * vectorDot(data.mu.vector, target.vector) + target.sqMag
  );
  const theta = rad2deg * Math.acos(vectorDot(data.mu.unit, target.unit));
  const rawPhi = Math.abs(data.mu.hue - target.hue);
  return {
    sigma,
    bigTheta: 1 - vectorDot(data.nu, target.unit),
    alpha: sigma * Math.pow(bigTheta, target.chroma + target.lightness),

    theta,
    phi: Math.min(rawPhi, 360 - rawPhi),
    delta: vectorMag(data.mu.vector.map((x, i) => x - target.vector[i])),
    manhattan: data.mu.vector
      .map((x, i) => Math.abs(x - target.vector[i]))
      .reduce((x, y) => x + y),
    ch: Math.max(...data.mu.vector.map((x, i) => Math.abs(x - target.vector[i]))),
    lightnessDiff: Math.abs(data.mu.lightness - target.lightness),

    inertia: data.inertia,
    variance: data.inertia - data.mu.sqMag,
    muNuAngle: data.muNuAngle,
    size: data.size,
    lightness: data.mu.lightness,
    chroma: data.mu.chroma,
    importance: data.importance,
  };
};

const currentScores = {};
const currentBestClusterIndices = {};
let sortedData = pokemonData;

const updateScores = (rgb) => {
  const { J, a, b } = d3.jab(rgb);
  const targetJab = buildVectorData([J, a, b], jab2hue, jab2lit, jab2chroma, jab2hex);
  const targetRgb = buildVectorData(
    [rgb.r, rgb.g, rgb.b],
    rgb2hue,
    rgb2lit,
    rgb2chroma,
    rgb2hex
  );
  pokemonData.forEach(({ name, jab, rgb }) => {
    currentScores[name] = {
      jab: {
        total: calcScores(jab.total, targetJab),
        clusters: jab.clusters.map((c) => calcScores(c, targetJab)),
      },
      rgb: {
        total: calcScores(rgb.total, targetRgb),
        clusters: rgb.clusters.map((c) => calcScores(c, targetRgb)),
      },
    };
    currentBestClusterIndices[name] = {
      // TODO
      jab: 0,
      rgb: 0,
    };
  });
};

const updateSort = () => {
  // TODO
};

const showResults = (resultsToDisplay) => {
  // TODO
};

window.onload = () => {
  const metricTemplate = document.getElementById("metric-form-template").content;

  selectors.sortControl.metric.appendChild(metricTemplate.cloneNode(true));
  selectors.sortControl.metricKind.value = "whole";
  selectors.sortControl.whole.value = "alpha";
  onMetricChange(selectors.sortControl);

  selectors.clusterControl.metric.appendChild(metricTemplate.cloneNode(true));
  selectors.clusterControl.sortOrder.checked = true;
  selectors.clusterControl.metricKind.value = "statistic";
  selectors.clusterControl.statistic.value = "importance";
  onMetricChange(selectors.clusterControl);
};
