/**
 * LANE-RENDER — era skins (style guide §8).
 *
 * "Reel Beds = sepia/brass/celluloid; Broadcast = phosphor green + wood-grain TV;
 *  Disc = rainbow-on-black gloss; Stream = flat white plastic + LED; Fortress =
 *  blinding matte white."
 *
 * Plumbing only this round. A machine's era is DERIVED from which tech unlocks it, so
 * when LANE-DATA adds reel/broadcast techs those machines re-skin with zero renderer
 * work. Machines no tech unlocks are starting equipment and take the default.
 *
 * The skin touches the CHASSIS only — the emissive accent stays the colour of what the
 * machine makes, because that's the resource, not the decade.
 *
 * `stream` is deliberately the identity skin (same roughness/metalness as the base body
 * material, no tint), so today's look is byte-for-byte unchanged until data says otherwise.
 */
import * as THREE from 'three';
import type { GameData, TechDef } from '../contracts';

export type Era = TechDef['era'];
export const DEFAULT_ERA: Era = 'stream';

export interface EraSkin {
  /** Multiplied into the chassis colour — 0xffffff leaves DATA's value alone. */
  tint: number;
  roughness: number;
  metalness: number;
}

export const ERA_SKIN: Record<Era, EraSkin> = {
  reel: { tint: 0xffd2a0, roughness: 0.65, metalness: 0.45 }, // sepia/brass/celluloid
  broadcast: { tint: 0xc4e8c4, roughness: 0.8, metalness: 0.1 }, // phosphor + woodgrain
  disc: { tint: 0x9aa0b8, roughness: 0.2, metalness: 0.65 }, // rainbow-on-black gloss
  stream: { tint: 0xffffff, roughness: 0.85, metalness: 0.15 }, // identity — the default
  fortress: { tint: 0xffffff, roughness: 0.95, metalness: 0.0 }, // blinding matte white
};

/**
 * machine id -> era, via the tech that unlocks it. Anything unmapped is starting
 * equipment (no tech gates it) and takes DEFAULT_ERA.
 */
export function eraIndex(data: GameData): Map<string, Era> {
  const out = new Map<string, Era>();
  const machines = new Set(data.machines.map((m) => m.id));
  for (const t of data.tech) {
    for (const u of t.unlocks) if (machines.has(u)) out.set(u, t.era);
  }
  return out;
}

/** Skin a chassis material in place. Accents must never be passed here. */
export function applyEraSkin(mat: THREE.MeshStandardMaterial, era: Era): void {
  const skin = ERA_SKIN[era] ?? ERA_SKIN[DEFAULT_ERA];
  mat.color.multiply(new THREE.Color(skin.tint));
  mat.roughness = skin.roughness;
  mat.metalness = skin.metalness;
}

/**
 * Era read as a SIGNAL rather than a surface — used by the locked-build ghost to say
 * *which* era is holding a machine back. `ERA_SKIN.tint` can't do this job: it's a
 * multiplier tuned to leave DATA's chassis alone (stream is literally white), so three
 * of the five eras would tell you nothing. These are chosen to be told apart at a
 * glance, in codex order.
 */
export const ERA_TELL: Record<Era, number> = {
  reel: 0xd8a24a, // brass
  broadcast: 0x5fd08a, // phosphor
  disc: 0x6fd7ff, // iridescent
  stream: 0xdfe6f2, // flat plastic white
  fortress: 0xf2f7ff, // blinding
};
