// A trigger zone, as an aspect on a Node2D. Requires a Shape2D (its geometry); creates a static SENSOR
// body from it, so a physics body overlapping the zone fires the node's 'enter' / 'exit' events
// instead of colliding. A trigger does not block movement.
//
//   const goal = new Node2D({ ... })
//     .aspect(Shape2D, { box: [32, 64] })
//     .aspect(Trigger2D)
//   goal.addEventListener('enter', other => win(other))
//   goal.addEventListener('exit',  other => ...)
//
// (A trigger is still pointer-pickable — clicks hit sensor shapes too.)

import { Aspect } from "../core/Aspect"
import { cx, cy, type Vec2Like } from "../math/vec"
import { ensurePhysicsEvents } from "./loop"
import { Shape2D } from "./Shape2D"
import type { Node2D } from "./Node2D"

export class Trigger2D extends Aspect<"trigger", Node2D> {
  static readonly aspect = "trigger"

  private _h = 0
  /** Native physics body id (0 if no physics support). Mirrors 3D `Trigger.id`. */
  get id(): number { return this._h }

  onAttach(): void {
    if (!_creator2d.physicsHasSupport || !_creator2d.physicsHasSupport()) return
    const shape = this.node.get(Shape2D)
    if (!shape) {
      throw new Error("Trigger2D requires a Shape2D aspect — add it first: node.aspect(Shape2D, {…}).aspect(Trigger2D)")
    }
    this._h = _creator2d.physicsCreateBody(this.node.id, 0 /* static */)
    if (!this._h) return
    shape._addTo(this._h, true /* sensor */, 1, 0, 0)
    ensurePhysicsEvents()   // routes contact/sensor events → the node's 'enter' / 'exit'
  }

  onDetach(): void {
    if (this._h) { _creator2d.physicsRemoveBody(this._h); this._h = 0 }
  }

  /** Reposition the trigger zone to a world point. */
  moveTo(p: Vec2Like): this {
    if (this._h) _creator2d.physicsSetTransform(this._h, cx(p), cy(p), 0)
    return this
  }
}
