// The glassie run, pure half (docs/SCENARIOS.md): carry a wire rack of glasses
// through a nightclub crowd without redecorating the floor. Wobble physics and
// breakage rules live here so the feel is testable; the scene only reports
// bumps and steering.

export const RACK_GLASSES = 6;
/** Wobble at or past this breaks a glass (and the wobble sheds with it). */
export const BREAK_AT = 1;
/** A break dumps you back here — shaken, not reset. */
const AFTER_BREAK = 0.45;
/** Passive settle per second when you walk smoothly. */
const SETTLE_PER_S = 0.35;
/** One crowd bump is most of the way to trouble on a settled rack. */
const BUMP_WOBBLE = 0.55;
/** Full-lock steering reversal adds this much per second. */
const TURN_WOBBLE_PER_S = 1.4;
/** In-game minutes between racks — the bar never stops producing empties. */
export const RACK_RESPAWN_MIN = 22;

export interface RackState {
  glasses: number;
  wobble: number;
}

export const freshRack = (): RackState => ({ glasses: RACK_GLASSES, wobble: 0 });

/**
 * Advance the rack one frame. `turnSharpness` is 0..1 (how hard the carry
 * velocity swung this frame); `bumped` is a de-bounced crowd contact.
 * Returns the new state plus how many glasses broke THIS frame (0 or 1 — a
 * frame only ever breaks one; the wobble shed makes chains possible but earned).
 */
export function stepRack(
  rack: RackState,
  dtMs: number,
  bumped: boolean,
  turnSharpness: number,
): { rack: RackState; broke: number } {
  const dt = Math.max(0, dtMs) / 1000;
  let wobble = rack.wobble - SETTLE_PER_S * dt;
  wobble += Math.max(0, Math.min(1, turnSharpness)) * TURN_WOBBLE_PER_S * dt;
  if (bumped) wobble += BUMP_WOBBLE;
  wobble = Math.max(0, wobble);

  if (wobble >= BREAK_AT && rack.glasses > 0) {
    return { rack: { glasses: rack.glasses - 1, wobble: AFTER_BREAK }, broke: 1 };
  }
  return { rack: { glasses: rack.glasses, wobble }, broke: 0 };
}

/** 0..1 steering harshness from consecutive frame velocities. */
export function turnSharpness(
  prevVx: number,
  prevVy: number,
  vx: number,
  vy: number,
  maxSpeed: number,
): number {
  if (maxSpeed <= 0) return 0;
  const dx = vx - prevVx;
  const dy = vy - prevVy;
  return Math.min(1, Math.hypot(dx, dy) / (maxSpeed * 2));
}
