//https://github.com/mrdoob/three.js/blob/dev/src/math/MathUtils.js

const DEG2RAD = Math.PI / 180;
const RAD2DEG = 180 / Math.PI;

export const mapLinear = (
  x: number,
  [a1, a2]: [number, number],
  [b1, b2]: [number, number],
) => {
  return b1 + ((x - a1) * (b2 - b1)) / (a2 - a1);
};

export const clamp = (x: number, min: number, max: number) =>
  x < min ? min : x > max ? max : x;

export const lerp = (x: number, y: number, t: number) => (1 - t) * x + t * y;

// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
export const damp = (x: number, y: number, lambda: number, dt: number) =>
  lerp(x, y, 1 - Math.exp(-lambda * dt));

export const degToRad = (degrees: number) => degrees * DEG2RAD;

export const radToDeg = (radians: number) => radians * RAD2DEG;

// Compute euclidean modulo of m % n
// https://en.wikipedia.org/wiki/Modulo_operation
export const euclideanModulo = (n: number, m: number) => ((n % m) + m) % m;

// Convert from Polar Coordinates (r,θ) to Cartesian Coordinates (x,y)
export const polarToCartesian = (radius: number, theta: number) => {
  const x = radius * Math.cos(theta);
  const y = radius * Math.sin(theta);
  return { x, y };
};

export const calculateArcPosition = (
  angle: number,
  radius: number = 1,
  xOffset: number = 0,
  yOffset: number = 0,
) => {
  const angleInRadians = degToRad(angle);
  const { x, y } = polarToCartesian(radius, angleInRadians);
  return { x: x + xOffset, y: y + yOffset };
};

export const radiusFromDiameter = (diameter: number): number => diameter / 2;

export const diameterFromRadius = (radius: number): number => 2 * radius;

export const circumferenceFromRadius = (radius: number) => 2 * Math.PI * radius;

export const radiusFromCircumference = (circumference: number) =>
  circumference / (2 * Math.PI);

export const wrap = (m: number, n: number) => {
  return n >= 0 ? n % m : ((n % m) + m) % m;
};
