import type { DataXY } from 'cheminfo-types';

import type { PointWithIndex } from '../types/index.ts';
import { xFindClosestIndex } from '../x/index.ts';

import { xyCheck } from './xyCheck.ts';

export interface XYMinClosestYPointOptions {
  target?: number;
  /**@default 0 */
  targetIndex?: number;
}

/**
 * Find the closest minimum going down hill
 * @param data - object that contains property x (an ordered increasing array) and y (an array).
 * @param options - options.
 * @returns an object with the x/y value.
 */
export function xyMinClosestYPoint(
  data: DataXY,
  options: XYMinClosestYPointOptions = {},
): PointWithIndex {
  xyCheck(data);
  const { x, y } = data;

  const { target } = options;
  let { targetIndex } = options;

  if (targetIndex === undefined) {
    if (target !== undefined) {
      targetIndex = xFindClosestIndex(x, target);
    } else {
      targetIndex = 0;
    }
  }

  let previousIndex = Number.MIN_SAFE_INTEGER;
  let currentIndex = targetIndex;

  let minY = y[targetIndex];

  while (currentIndex !== previousIndex) {
    previousIndex = currentIndex;
    if (currentIndex > 0 && y[currentIndex - 1] < minY) {
      currentIndex--;
    } else if (currentIndex < x.length - 1 && y[currentIndex + 1] < minY) {
      currentIndex++;
    }
    minY = y[currentIndex];
  }
  return {
    x: x[currentIndex],
    y: y[currentIndex],
    index: currentIndex,
  };
}
