/**
 * Lane G demo — colour zones, paint puddles, and the MEGA/MINI scale fork.
 *
 * Builds the REAL greybox + blob + controller, then lays Lane G on top via
 * installZones (puddles + purple/pink fork + low tunnel). Drive through and watch
 * coverage climb by ROUTE — no aiming, no cannon luck. The HUD reads live coverage
 * / modifiers, whether the MEGA pressure plate has tripped, and your size so you
 * can see MEGA grow and MINI shrink.
 *
 * The three things this demo proves (acceptance):
 *   1. A hold-forward run (press F) ends ≥40% painted with a buff active — puddles
 *      guarantee it. The console STATE line reports total% + active buffs.
 *   2. PURPLE puddle → MEGA (grow + heavy) → trips the left pressure plate → boot
 *      yeet. A clean blob rolls over the plate without tripping it.
 *   3. PINK puddle → MINI (shrink) → fits the low pink tunnel on the right. A
 *      normal/clean blob bonks the roof and can't pass.
 *
 * CONTROLS
 *   WASD / Arrows   move (camera-relative)      Space  jump
 * DEBUG KEYS
 *   F   toggle AUTO hold-forward (hands-free straight run through the zones)
 *   1   teleport to RED start        2  teleport to the BLUE river
 *   3   teleport to the PURPLE (left/MEGA) fork mouth
 *   4   teleport to the PINK (right/MINI) tunnel mouth
 *   X   full cleanse (go clean — then try the tunnel/plate to see the difference)
 *   C   cleanse 50%
 *   R   respawn at start (also cleanses)
 *   P   print a STATE snapshot to the console
 *   H   toggle the HUD
 * A STATE line prints once/second: pos, coverage %s, size/mass, active buffs, plate.
 */
import * as THREE from 'three'
import { createWorld } from '../world'
import { buildGreybox } from '../course/greybox'
import { createBlob } from '../blob/createBlob'
import { createBlobController } from '../blob/controller'
import { createBlobFeel } from '../blob/feel'
import { createFollowCamera } from '../blob/camera'
import { PaintSkin, PaintCannon, BuffSystem, PaintHUD, installPaint, COLOR_ORDER } from '../paint'
import { installZones } from '../course/zones'

const world = await createWorld(document.getElementById('app')!)
const course = buildGreybox(world)

// ---- blob + Lane A layers (controller/feel/camera) ----
const blob = createBlob(world, { position: course.spawn })
blob.paint = new PaintSkin(blob.mesh, { size: 256 })
world.blob = blob
const skin = blob.paint as PaintSkin

world.addSystem(createBlobController(world, blob))
const feel = createBlobFeel(blob)
world.events.on('blob:jumped', () => feel.onJump())
world.events.on('blob:landed', (p: { impact: number }) => feel.onLand(p.impact))
world.onFrame((dt) => feel.update(dt))
const camera = createFollowCamera(world, blob)
world.onFrame((dt) => camera.update(dt))

// ---- buffs + inbound paint protocol ----
world.addSystem(new BuffSystem(world, { mesh: blob.mesh, modifiers: blob.modifiers, paint: skin }))
installPaint(world, { mesh: blob.mesh, paint: skin })

// ---- LANE G: zones (puddles) + purple/pink fork + low tunnel ----
const zones = installZones(world, blob, skin)

// ---- stage the returned cannon configs as bonus pressure (integration's job in
// the real game; done here so the demo shows cannons + puddles together) ----
for (const c of zones.cannonConfigs) {
  world.addSystem(new PaintCannon({
    world,
    position: new THREE.Vector3(...c.position),
    color: c.color,
    target: blob.mesh,
    paint: skin,
    targetRadius: blob.radius,
    triggerId: c.triggerId,
    interval: c.interval,
    muzzleSpeed: 26,
    splatRadius: 0.45,
  }))
}

// ---- demo-only gap trampoline (stands in for game.ts's real one) so an AUTO
// hold-forward run can clear the shelf gap instead of soft-locking in the slot ----
{
  world.physics.createCollider(
    world.rapier.ColliderDesc.cuboid(6, 0.25, 2).setTranslation(0, 0.25, 0))
  const tramp = new THREE.Mesh(
    new THREE.BoxGeometry(12, 0.5, 4),
    new THREE.MeshStandardMaterial({ color: '#FF9500', roughness: 0.6 }))
  tramp.position.set(0, 0.25, 0)
  world.scene.add(tramp)
  let cd = 0
  world.addSystem({
    update(dt) {
      cd = Math.max(0, cd - dt)
      const t = blob.body.translation()
      const v = blob.body.linvel()
      if (Math.abs(t.x) < 6 && t.z > -2.2 && t.z < 2.2 && t.y < 1.4 && v.y < 0.5 && cd === 0) {
        blob.body.setLinvel({ x: v.x * 0.4, y: 14, z: Math.max(-3, Math.min(3, (0.5 - t.z) * 1.5)) }, true)
        cd = 0.6
        world.events.emit('blob:jumped', {})
      }
    },
  })
}

// ---- MEGA plate telemetry: did purple weight trip it? ----
let plateTripped = false
world.events.on('machine:signal', (p: { id: string }) => {
  if (p.id === zones.bootSignal) {
    plateTripped = true
    console.log('%c[zone] PRESSURE PLATE TRIPPED — MEGA is heavy enough. BOOT YEET!', 'color:#AF52DE;font-weight:700')
  }
})

// ---- AUTO hold-forward (dispatch a held KeyW so the real controller drives) ----
let auto = false
function setAuto(on: boolean) {
  auto = on
  const type = on ? 'keydown' : 'keyup'
  dispatchEvent(new KeyboardEvent(type, { code: 'KeyW' }))
  console.log(`[demo] AUTO hold-forward ${on ? 'ON' : 'OFF'}`)
}
// re-assert the held key each second (some browsers coalesce synthetic repeats)
world.onFrame(() => { if (auto) dispatchEvent(new KeyboardEvent('keydown', { code: 'KeyW' })) })

function respawn() {
  blob.body.setTranslation({ x: course.spawn.x, y: course.spawn.y, z: course.spawn.z }, true)
  blob.body.setLinvel({ x: 0, y: 0, z: 0 }, true)
  skin.cleanse(1)
  plateTripped = false
}
function teleport(x: number, y: number, z: number, label: string) {
  blob.body.setTranslation({ x, y, z }, true)
  blob.body.setLinvel({ x: 0, y: 0, z: 0 }, true)
  console.log(`[demo] teleport → ${label}`)
}
world.onFrame(() => { if (blob.body.translation().y < -25) respawn() })

// ---- HUD (declared before the key handler that toggles it) ----
const hud = new PaintHUD()

addEventListener('keydown', (e) => {
  switch (e.code) {
    case 'KeyF': setAuto(!auto); break
    case 'Digit1': teleport(0, 2.5, 20, 'RED start'); break
    case 'Digit2': teleport(0, 1.0, -26, 'BLUE river'); break
    case 'Digit3': teleport(-6, 1.0, -37, 'PURPLE / MEGA fork mouth'); break
    case 'Digit4': teleport(6.5, 0.8, -37, 'PINK / MINI tunnel mouth'); break
    case 'KeyX': skin.cleanse(1); console.log('[demo] full cleanse — blob is CLEAN'); break
    case 'KeyC': skin.cleanse(0.5); console.log('[demo] cleanse 50%'); break
    case 'KeyR': respawn(); break
    case 'KeyP': console.log('[STATE]', JSON.stringify(snapshot())); break
    case 'KeyH': hud.root.style.display = hud.root.style.display === 'none' ? '' : 'none'; break
    default: return
  }
})

// ---- telemetry -------------------------------------------------------------
function snapshot() {
  const cov = skin.coverage()
  const t = blob.body.translation()
  const m = blob.modifiers
  return {
    pos: [+t.x.toFixed(1), +t.y.toFixed(1), +t.z.toFixed(1)],
    total: +(cov.total * 100).toFixed(0),
    colours: COLOR_ORDER.filter((c) => cov.byColor[c] > 0.005).map((c) => `${c}:${(cov.byColor[c] * 100).toFixed(0)}%`),
    size: +m.size.toFixed(2),
    mass: +m.massMul.toFixed(2),
    stamps: zones.totalStamps(),
    plateThreshold: +zones.plateThreshold.toFixed(2),
    plateTripped,
    tunnelUndersideY: zones.tunnel.roofUndersideY,
  }
}

let acc = 0
world.onFrame((dt) => {
  const cov = skin.coverage()
  hud.update(cov, blob.modifiers)
  acc += dt
  if (acc >= 1) {
    acc = 0
    const s = snapshot()
    const m = blob.modifiers
    const buffs = [
      m.speedMul > 1.001 ? `speed×${m.speedMul.toFixed(2)}` : '',
      m.grip > 0.001 ? `grip${m.grip.toFixed(2)}` : '',
      m.waterproof ? 'waterproof' : '',
      m.size > 1.05 ? `MEGA×${m.size.toFixed(2)}` : m.size < 0.95 ? `MINI×${m.size.toFixed(2)}` : '',
      m.glow > 0 ? 'SUPER' : '',
    ].filter(Boolean).join(' ') || '(none)'
    console.log(
      `[STATE] pos=(${s.pos.join(',')}) total=${s.total}% ${s.colours.join(' ') || '(clean)'} | ` +
      `size=${s.size} mass=${s.mass} | buffs: ${buffs} | plate ${plateTripped ? 'TRIPPED' : 'armed'} | stamps=${s.stamps}`,
    )
  }
})

world.start()
console.log('%cBLOBBO Lane G — colour zones · puddles · MEGA/MINI', 'color:#AF52DE;font-weight:700')
console.log('WASD move · Space jump · F auto-forward · 1-4 teleport zones · X clean · C cleanse50 · R respawn · P state · H hud')
