"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.workoutColorForValue = workoutColorForValue;
var _coloring = require("@kbn/coloring");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

function findColorSegment(value, comparison, colors, rangeMin, rangeMax) {
  var _colors$index;
  // assume uniform distribution within the provided range, can ignore stops
  const step = (rangeMax - rangeMin) / colors.length;

  // what about values in range
  const index = colors.findIndex((c, i) => comparison(value, rangeMin + (1 + i) * step) <= 0);
  // see comment below in function 'findColorsByStops'
  return (_colors$index = colors[index]) !== null && _colors$index !== void 0 ? _colors$index : value >= rangeMin + colors.length * step ? colors[colors.length - 1] : colors[0];
}
function findColorsByStops(value, comparison, colors, stops) {
  var _colors$index2;
  const index = stops.findIndex(s => comparison(value, s) < 0);
  // as we now we can provide 'rangeMax' as end for last interval (iterval [lastStop, rangeMax]),
  // value can be more that last stop but will be valid
  // because of this we should provide for that value the last color.
  // (For example, value = 100, last stop = 80, rangeMax = 120, before we was return the first color,
  //  but now we will return the last one)
  return (_colors$index2 = colors[index]) !== null && _colors$index2 !== void 0 ? _colors$index2 : value >= stops[stops.length - 1] ? colors[colors.length - 1] : colors[0];
}
function getNormalizedValueByRange(value, {
  range,
  rangeMin
}, minMax) {
  let result = value;
  if (range === 'percent') {
    result = 100 * (value - minMax.min) / (minMax.max - minMax.min);

    // a division by zero safeguard is required if the range above has equal boundaries
    if (!Number.isFinite(result)) {
      return rangeMin;
    }
  }
  return result;
}
const getNormalizedMaxRange = ({
  stops,
  colors,
  rangeMax
}, isMaxContinuity, [min, max]) => {
  if (isMaxContinuity) {
    return Number.POSITIVE_INFINITY;
  }
  return stops.length ? rangeMax : max - (max - min) / colors.length;
};
const getNormalizedMinRange = ({
  stops,
  rangeMin
}, isMinContinuity, min) => {
  if (isMinContinuity) {
    return Number.NEGATIVE_INFINITY;
  }
  return stops.length ? rangeMin : min;
};

/**
 * When stops are empty, it is assumed a predefined palette, so colors are distributed uniformly in the whole data range
 * When stops are passed, then rangeMin/rangeMax are used as reference for user defined limits:
 * continuity is defined over rangeMin/rangeMax, not these stops values (rangeMin/rangeMax are computed from user's stop inputs)
 */
function workoutColorForValue(value, params, minMax) {
  if (value == null) {
    return;
  }
  const {
    colors,
    stops,
    range = 'percent',
    continuity = 'above',
    rangeMax,
    rangeMin
  } = params;
  const isMinContinuity = (0, _coloring.checkIsMinContinuity)(continuity);
  const isMaxContinuity = (0, _coloring.checkIsMaxContinuity)(continuity);
  // ranges can be absolute numbers or percentages
  // normalized the incoming value to the same format as range to make easier comparisons
  const normalizedValue = getNormalizedValueByRange(value, params, minMax);
  const [min, max] = range === 'percent' ? [0, 100] : [minMax.min, minMax.max];
  const minRange = getNormalizedMinRange({
    stops,
    rangeMin
  }, isMinContinuity, min);
  const maxRange = getNormalizedMaxRange({
    stops,
    colors,
    rangeMax
  }, isMaxContinuity, [min, max]);
  const comparisonFn = (v, threshold) => v - threshold;
  if (comparisonFn(normalizedValue, minRange) < 0) {
    if (isMinContinuity) {
      return colors[0];
    }
    return;
  }
  if (comparisonFn(normalizedValue, maxRange) > 0) {
    if (isMaxContinuity) {
      return colors[colors.length - 1];
    }
    return;
  }
  if (stops.length) {
    return findColorsByStops(normalizedValue, comparisonFn, colors, stops);
  }
  return findColorSegment(normalizedValue, comparisonFn, colors, min, max);
}