// Loop — a layer's LOOP: what it shows when no one-shot plays (`anim.playLoop('Idle')` — one looping clip,
// or `anim.playLoop({ Idle: 0, Walking: 2, Run: 6 })` — a blend whose members loop in phase and `value`
// picks the mix: 1D linear between neighbours, `[x, y]` positions = a 2D gradient band). One-shots fade
// it out and return to it; `playLoop(next)` crossfades to another; `stop()` removes it. The object
// returned by `playLoop()` (also `anim.loop`) is the handle; a replaced loop's object goes dead.

import type { BlendPosition, Core, LoopRec } from "./core"

export class Loop {
  private readonly _r: LoopRec
  private readonly _c: Core
  /** @internal — created by playLoop(). */
  constructor(rec: LoopRec, core: Core) { this._r = rec; this._c = core }

  /** Position on the axis (number) or plane (`[x, y]`) — units are whatever the positions use. Live
   *  even while a one-shot plays (the loop returns at the new mix). */
  get value(): BlendPosition { return this._r.value }
  set value(v: BlendPosition) { this._c.setLoopValue(this._r, v) }
  /** Where the loop is in its cycle, 0–1 — one clock for every member (a blend cycles over its
   *  weighted period). Set it to jump the cycle: `playLoop(def, { phase })` on the way in, or here
   *  to re-sync with something else (a clip whose pose matches the cycle at that phase). */
  get phase(): number { return this._c.loopPhase(this._r) }
  set phase(v: number) { this._c.setLoopPhase(this._r, v) }
  /** Each member's current contribution, 0–1 (fades included). */
  get weights(): Record<string, number> {
    const out: Record<string, number> = {}
    for (const m of this._r.members) out[m.name] = this._c.slotWeight(m.slot)
    return out
  }
}
