import type { Vec3 } from "../../engine/math/Vec3"
import type { Actor } from "../../engine/scene/Actor"
import type { RenderTransform } from "../../engine/render/RenderScene"
import type { BoxCollider } from "../../engine/world/Collider"
import type { Terrain } from "../../engine/world/Terrain"

/** Runtime actor using shared roaming-creature state. Concrete definitions are
 * direct object references supplied by Frog, Bee, Robin, or future content. */
export type Mob = Actor<Terrain>

export type MobState = {
  /** Leash anchor (where it was scattered); wandering is pulled back toward it. */
  home: Vec3
  /** Live feet-center (frog/robin) / body-center (bee), advanced each frame. */
  position: Vec3
  /** Facing yaw; the mesh's front is local +Z, so world dir = (sin h, 0, cos h). */
  heading: number
  /** Per-instance size multiplier. */
  scale: number
  /** Evolving RNG state (mutated by `update`) -- keeps the sim deterministic. */
  seed: number
  /** Horizontal velocity (frog/robin: mid-hop or -flight; bee: cruise). */
  vx: number
  vz: number
  /** Vertical velocity (frog/robin ballistic hop/flight; bee stays 0, uses a bob). */
  vy: number
  /** Countdown to the next decision (frog/robin: next hop; bee: next heading change). */
  timer: number
  /** Behavior scratch clock: the bee's hover-bob phase; the robin's remaining
   *  powered-flight cruise time (>0 while gliding between perches). */
  phase: number
  /** Frog/robin: resting on the ground vs airborne (a hop or a flight). */
  grounded: boolean
}

export namespace Mob {
  export function transform(state: MobState): RenderTransform {
    return {
      x: state.position.x,
      y: state.position.y,
      z: state.position.z,
      heading: state.heading,
      scale: state.scale,
    }
  }

  export function collider(
    state: MobState,
    radius: number,
    height: number,
    standable: boolean,
  ): BoxCollider {
    const half = radius * state.scale * 0.7
    return {
      shape: "box",
      minX: state.position.x - half,
      maxX: state.position.x + half,
      minZ: state.position.z - half,
      maxZ: state.position.z + half,
      top: state.position.y + height * state.scale,
      standable,
    }
  }
}
