// Pointer event objects delivered to 3D scene/node touch handlers. Ported from worker/src/TouchEvent.ts.
// The dispatch wiring (reading the active scene, hit entity) is set up in Phase 4 with the 3D Scene;
// these classes are the injected globals user code receives. `target` is the hit Node (typed loosely
// here to avoid a forward dependency on gl/).

export class ClickEvent<T = any> {
  readonly type = "click"
  readonly pointerId: number
  readonly clientX: number
  readonly clientY: number
  /** World-space hit position (2D scenes only; undefined in 3D). */
  worldX?: number
  worldY?: number
  target!: T
  constructor(clientX: number, clientY: number, pointerId: number) {
    this.clientX = clientX
    this.clientY = clientY
    this.pointerId = pointerId
  }
}

export interface TrackHandler {
  onMove?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
  onEnd?(pos: { clientX: number, clientY: number, deltaX: number, deltaY: number }): void
  onCancel?(): void
  claim?: boolean | "pan-x" | "pan-y" | "pan-down" | "pan-up" | "pan-left" | "pan-right"
}

export class TouchStartEvent<T = any> {
  readonly type = "touchstart"
  readonly pointerId: number
  readonly clientX: number
  readonly clientY: number
  /** World-space hit position (2D scenes only; undefined in 3D). */
  worldX?: number
  worldY?: number
  target!: T
  /** @internal — read by the dispatch system after the handler runs. */
  _trackHandler?: TrackHandler
  constructor(clientX: number, clientY: number, pointerId: number) {
    this.clientX = clientX
    this.clientY = clientY
    this.pointerId = pointerId
  }

  /** Capture subsequent moves/end for this pointer (drag/pan gestures). */
  track(handler: TrackHandler): void {
    this._trackHandler = handler
  }
}

/** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the
 *  host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —
 *  so the common "press-and-hold, then drag to move" flow is one handler: start the drag from here. */
export class LongPressEvent<T = any> {
  readonly type = "longpress"
  readonly pointerId: number
  readonly clientX: number
  readonly clientY: number
  /** World-space hit position (2D scenes only; undefined in 3D). */
  worldX?: number
  worldY?: number
  target!: T
  /** @internal — read by the dispatch system after the handler runs. */
  _trackHandler?: TrackHandler
  constructor(clientX: number, clientY: number, pointerId: number) {
    this.clientX = clientX
    this.clientY = clientY
    this.pointerId = pointerId
  }

  /** Capture subsequent moves/end for this pointer — drag the element after the hold. */
  track(handler: TrackHandler): void {
    this._trackHandler = handler
  }
}
