import type { Measurements } from "../image/analyze.js";
import type { BodyType } from "./types.js";

/**
 * Authored body proportions for the two base meshes.
 *
 * These are the single source of truth for figure shape: `buildSkeleton` reads
 * the landmarks, `bodyMetrics` reads the widths, and every garment sizes itself
 * off the metrics. Change a number here and the skin, the clothes and the rig
 * all move together.
 *
 * Values are fractions of total height — landmarks measured **down from the
 * crown**, widths as **full breadth** (so `hip: 0.19` on a 1.78 m figure is a
 * 34 cm hip). They sit close to standard adult anthropometry (a 7.5-head
 * figure) rather than the FF8 lanky read the first pass used: the art
 * direction in `tools/fixtures/survivor-reference.jpg` is grounded
 * survival-horror, where a stick figure reads as a child at 240p.
 *
 * The stylisation lives elsewhere — low ring counts, hard facets, flat colour.
 * The proportions themselves stay honest so silhouettes read at distance and
 * animation retargeting behaves.
 */

function landmark(y: number) {
  return { y, source: "derived" as const };
}

/** Adult male — 7.5 heads, moderate shoulder V, real limb girth. */
export const MALE_MEASUREMENTS: Measurements = {
  pixelHeight: 1000,
  pixelWidth: 440,
  landmarks: {
    // Neck base sits at the trapezius line, not under the jaw — the old 0.12
    // gave a swan neck that made the head look shrunken.
    neck: landmark(0.175),
    shoulder: landmark(0.182),
    chest: landmark(0.26),
    waist: landmark(0.37),
    hip: landmark(0.48),
    crotch: landmark(0.52),
    knee: landmark(0.715),
    ankle: landmark(0.955),
  },
  widths: {
    head: 0.087,
    neck: 0.062,
    // Biacromial (bone). The deltoids push the silhouette out to ~0.26.
    shoulder: 0.245,
    chest: 0.174,
    waist: 0.155,
    hip: 0.191,
    thigh: 0.098,
    calf: 0.068,
    foot: 0.055,
    upperArm: 0.058,
    forearm: 0.05,
  },
  // Half the arm span: centreline to fingertip. Vitruvian — span ≈ height.
  armReach: 0.51,
  stance: 0.048,
  aspect: 2.4,
};

/** Adult female — narrower shoulders, higher and narrower waist, wider hips. */
export const FEMALE_MEASUREMENTS: Measurements = {
  pixelHeight: 1000,
  pixelWidth: 415,
  landmarks: {
    neck: landmark(0.172),
    shoulder: landmark(0.18),
    chest: landmark(0.265),
    waist: landmark(0.355),
    hip: landmark(0.485),
    crotch: landmark(0.525),
    knee: landmark(0.715),
    ankle: landmark(0.955),
  },
  widths: {
    head: 0.084,
    neck: 0.055,
    shoulder: 0.215,
    chest: 0.163,
    waist: 0.136,
    hip: 0.202,
    thigh: 0.1,
    calf: 0.062,
    foot: 0.05,
    upperArm: 0.05,
    forearm: 0.043,
  },
  armReach: 0.49,
  stance: 0.044,
  aspect: 2.45,
};

export function measurementsFor(body: BodyType): Measurements {
  return body === "female" ? FEMALE_MEASUREMENTS : MALE_MEASUREMENTS;
}

/** Default heights when a recipe doesn't set one. */
export const DEFAULT_HEIGHT: Record<BodyType, number> = {
  male: 1.78,
  female: 1.66,
};
