// Layer — one layer of an Animator (`anim.addLayer({ mask: 'Spine1' })` for the upper body,
// `{ additive: true }` for deltas stacked on top). The Animator's own play/stop/playLoop ARE its base
// layer; extra layers composite over it in creation order. The object is the layer's only handle.

import type { ActiveClip, Core, LayerRec, LoopDef, LoopOptions, PlayOptions, StopOptions } from "./core"
import type { Loop } from "./Loop"
import type { Playback } from "./Playback"

export class Layer {
  private readonly _r: LayerRec
  private readonly _c: Core
  /** @internal — created by the Animator. */
  constructor(rec: LayerRec, core: Core) { this._r = rec; this._c = core }

  /** Play a one-shot on this layer (crossfading per the options); resolves at its hand-over. */
  play(clip?: string | number, options: PlayOptions = {}): Playback { return this._c.play(this._r, clip, options) }
  /** Set / transition this layer's loop (a clip, or a blend space) — crossfades over `fade` from whatever
   *  the layer shows, a one-shot included (it is cut short). */
  playLoop(def: LoopDef, options: LoopOptions = {}): Loop | undefined { return this._c.loop(this._r, def, options) }
  /** Fade everything on this layer out — one-shots and its loop. */
  stop(options: StopOptions = {}): this { this._c.stopLayer(this._r, options.fade ?? 0); return this }
  /** This layer's current loop (the object the last `playLoop()` returned), if any. */
  get loop(): Loop | undefined { return this._r.loop?.view }
  /** Layer contribution 0–1. */
  get weight(): number { return this._r.weight }
  set weight(v: number) { this._r.weight = v; this._c.pushLayer(this._r) }
  /** A one-shot on this layer hasn't handed over yet. */
  get busy(): boolean { return this._c.busy(this._r) }
  /** Every clip this layer shows this frame with its weight — the crossfades' state, for a debug overlay. */
  get active(): ActiveClip[] { return this._c.active(this._r) }
}
