import type { ColliderDef, ColliderMaterial } from "./collision.js";
import type { Vec3 } from "./math.js";

/** A static piece of level geometry: one visual mesh + its collider compound. */
export interface StaticGeometryDef {
  id: string;
  /** Which builder in `client/src/world/geometry.ts` renders this piece. */
  visual:
    | { kind: "box"; size: Vec3; color: number; textureId?: string }
    | { kind: "plane"; size: [number, number]; color: number; textureId?: string }
    /** Rendered via ConvexGeometry so the mesh matches a hull collider exactly. */
    | { kind: "hull"; points: Vec3[]; color: number }
    | { kind: "none" };
  position: Vec3;
  /** Yaw in radians. Rooms are authored axis-aligned plus yaw; that is enough for the genre. */
  yaw?: number;
  colliders: ColliderDef[];
  material?: ColliderMaterial;
  /** Despawned once this flag is set — barred doors, collapsed debris, shutters. */
  removeOnFlag?: string;
}

/**
 * A fixed camera zone — GDD §6.1.
 *
 * The trigger is a box sensor. While the player is inside, the camera snaps to
 * `camera` and looks at `lookAt` (or tracks the player if `trackPlayer` is set).
 * Overlapping zones resolve by highest `priority`.
 */
export interface CameraZoneDef {
  id: string;
  trigger: { center: Vec3; halfExtents: Vec3 };
  camera: {
    position: Vec3;
    lookAt: Vec3;
    fov?: number;
    /** Follow the player with a damped look-at instead of a fixed target. */
    trackPlayer?: boolean;
    /** How far the camera may pan while tracking, in world units. */
    trackRadius?: number;
  };
  /** Hard cut (classic RE) or a timed blend (Silent Hill style). Seconds. */
  blend?: { mode: "cut" } | { mode: "blend"; duration: number };
  priority?: number;
}

export type InteractionKind =
  | { kind: "examine"; text: string }
  | { kind: "pickup"; itemId: string; quantity?: number }
  | { kind: "door"; targetRoomId: string; spawnPointId: string; requiresItemId?: string }
  | { kind: "useItem"; acceptsItemId: string; onUseFlag: string; text: string };

/** Something the player can walk up to and press Interact on. */
export interface InteractableDef {
  id: string;
  label: string;
  position: Vec3;
  /** Sensor half-extents defining the "you can reach this" volume. */
  halfExtents: Vec3;
  action: InteractionKind;
  /** Only active while every listed flag is set (or unset, when prefixed with `!`). */
  requiresFlags?: string[];
  /** Set to false once consumed; persisted in the save. */
  repeatable?: boolean;
  visual?: { kind: "box"; size: Vec3; color: number } | { kind: "none" };
}

export interface SpawnPointDef {
  id: string;
  position: Vec3;
  yaw: number;
}

export interface RoomDef {
  id: string;
  displayName: string;
  /** Linear fog, the primary atmosphere tool (GDD §14). */
  fog: { color: number; near: number; far: number };
  ambientLight: { color: number; intensity: number };
  lights: Array<{
    kind: "point" | "directional";
    color: number;
    intensity: number;
    position: Vec3;
    distance?: number;
  }>;
  geometry: StaticGeometryDef[];
  cameraZones: CameraZoneDef[];
  interactables: InteractableDef[];
  spawnPoints: SpawnPointDef[];
}
