import { addAlpha, extractAlpha } from '~/modules/alpha';
import { clamp, parseInput } from '~/modules/utils';

import { ConverterParameters, HSL, RGB } from '~/types';

/**
 * Convert RGB to HSL.
 *
 * @param input - The RGB color object or tuple.
 * @returns The HSL color object.
 */
export default function rgb2hsl(input: ConverterParameters<RGB>): HSL {
  const value = parseInput(input, 'rgb');
  const alpha = extractAlpha(input);

  const rLimit = clamp(value.r, 0, 255) / 255;
  const gLimit = clamp(value.g, 0, 255) / 255;
  const bLimit = clamp(value.b, 0, 255) / 255;

  const min = Math.min(rLimit, gLimit, bLimit);
  const max = Math.max(rLimit, gLimit, bLimit);
  const delta = max - min;

  let h = 0;
  let s;
  const l = (max + min) / 2;
  let rate;

  switch (max) {
    case rLimit:
      rate = !delta ? 0 : (gLimit - bLimit) / delta;
      h = 60 * rate;
      break;
    case gLimit:
      rate = (bLimit - rLimit) / delta;
      h = 60 * rate + 120;
      break;
    case bLimit:
      rate = (rLimit - gLimit) / delta;
      h = 60 * rate + 240;
      break;
    /* v8 ignore next 2  -- @preserve */
    default:
      break;
  }

  if (h < 0) {
    h = 360 + h;
  }

  if (min === max) {
    s = 0;
  } else {
    s = l < 0.5 ? delta / (2 * l) : delta / (2 - 2 * l);
  }

  return addAlpha(
    {
      h: Math.abs(+(h % 360).toFixed(2)),
      s: +(s * 100).toFixed(2),
      l: +(l * 100).toFixed(2),
    },
    alpha,
  );
}
