// Display formatting. The only place where whole millimetres turn back into cm, m, inches or feet.

import type { DisplayUnits } from "./config";

const trim = (n: number, digits: number) => String(Number(n.toFixed(digits)));

// A length in the shop's units: "56 cm" or "22 in". Short lengths keep one decimal place.
export function formatLength(mm: number, units: DisplayUnits): string {
  return units === "in" ? `${trim(mm / 25.4, 1)} in` : `${trim(mm / 10, 1)} cm`;
}

// A room or wall length: "3.2 m" or "10.5 ft".
export function formatRoomLength(mm: number, units: DisplayUnits): string {
  return units === "in" ? `${trim(mm / 304.8, 2)} ft` : `${trim(mm / 1000, 2)} m`;
}

export function formatArea(mm2: number, units: DisplayUnits): string {
  return units === "in" ? `${trim(mm2 / 92_903.04, 2)} sq ft` : `${trim(mm2 / 1_000_000, 2)} m²`;
}

// Paint: "2.5 L", or US gallons for imperial shops: "0.66 gal".
export function formatVolume(ml: number, units: DisplayUnits): string {
  return units === "in" ? `${trim(ml / 3_785.411784, 2)} gal` : `${trim(ml / 1_000, 2)} L`;
}

// A bag or a load: "20 kg", "1.2 tonnes", or pounds for imperial shops: "44.1 lb".
export function formatMass(g: number, units: DisplayUnits): string {
  if (units === "in") return `${Number((g / 453.59237).toFixed(1)).toLocaleString("en-GB")} lb`;
  if (g < 1_000_000) return `${Number((g / 1_000).toFixed(1)).toLocaleString("en-GB")} kg`;
  const tonnes = trim(g / 1_000_000, 2);
  return `${tonnes} ${tonnes === "1" ? "tonne" : "tonnes"}`;
}

// The volume of an area at a depth: "0.3 m³" or "10.6 cu ft".
export function formatCubic(mm3: number, units: DisplayUnits): string {
  return units === "in" ? `${trim(mm3 / 28_316_846.592, 1)} cu ft` : `${trim(mm3 / 1e9, 3)} m³`;
}

export function plural(n: number, one: string, many = `${one}s`): string {
  return `${n.toLocaleString("en-GB")} ${n === 1 ? one : many}`;
}

// The word alone, singular or plural, for a template placeholder such as "{unit}".
export function pluralWord(n: number, one: string, many = `${one}s`): string {
  return n === 1 ? one : many;
}

// Value for a number input, in the unit the shopper types (cm or in for designs; m or ft for rooms).
export function toInputValue(mm: number, unit: "cm" | "in" | "m" | "ft"): string {
  const divisor = { cm: 10, in: 25.4, m: 1000, ft: 304.8 }[unit];
  return trim(mm / divisor, unit === "cm" || unit === "in" ? 1 : 2);
}

export function fromInputValue(value: string, unit: "cm" | "in" | "m" | "ft"): number | null {
  const n = Number(value);
  if (value.trim() === "" || !Number.isFinite(n) || n <= 0) return null;
  const multiplier = { cm: 10, in: 25.4, m: 1000, ft: 304.8 }[unit];
  return Math.round(n * multiplier);
}
