/**
 * Utility to compute for a specific district the eased position of its dot
 * based on the current zoom level, the geographical center of the district,
 * and the zoom-level offsets for the district. When the zoom level falls
 * between multiple zoom-level offsets we ease between the offsets linearly
 * with zoom.
 *
 * @typedef {Object} CirclePosition
 * @property {number} cx
 * @property {number} cy
 *
 * @param {Object} opts
 * @param {number[]} opts.center
 *        The x and y coordinates of the geographical center of the district
 * @param {number[]} opts.keyframes
 *        Any keyframes for this district, each recorded as an `[x, y, k]`
 *        array where `[x, y]` is how offset the dot should be from `center` at
 *        the multiplicative zoom value `k`
 * @param {number} zoomLevel
 *        The current multiplicative zoom level of the map
 * @returns {CirclePosition}
 */
const getCenterForZoom = function getCenterForZoom(opts = {}) {
  const {
    center,
    keyframes,
    zoomLevel,
    ignoreKeyframes = false
  } = opts;
  if (!keyframes) {
    return {
      cx: center[0],
      cy: center[1]
    };
  }
  const secondStepIndex = keyframes.findIndex(keyframe => keyframe[2] > zoomLevel);
  const firstStepIndex = secondStepIndex < 1 ? keyframes.length - 1 : secondStepIndex - 1;
  const startOffset = keyframes[firstStepIndex];
  const [startX, startY, startLevel] = startOffset;
  const [endX, endY, endLevel] = keyframes[secondStepIndex] || startOffset;
  const levelRange = endLevel - startLevel;
  const t = (zoomLevel - startLevel) / (levelRange || 1);
  const easedX = startX + (endX - startX) * t;
  const easedY = startY + (endY - startY) * t;
  return {
    cx: center[0] + (ignoreKeyframes ? 0 : easedX),
    cy: center[1] + (ignoreKeyframes ? 0 : easedY)
  };
};
export default getCenterForZoom;