/**
 * Replay Player (W4.2 ↔ W3.1 bridge).
 *
 * Takes a ReplaySequence (W4.2 sandbox-replay fixture) and emits TimelineRow
 * events (W3.1 runtime-event-renderer output) on a JS timer. Used by the
 * dashboard's "Run Demo" button on the no-install demo path to play back
 * a sanitized agent run as if it were happening in real time.
 *
 * Player is pluggable:
 *   - tick callback fires per emitted row
 *   - done callback fires when the sequence completes (or is stopped)
 *   - speedMultiplier scales replay time (5x for "fast-forward" demos)
 *   - schedule defaults to globalThis.setTimeout but is injectable for tests
 *
 * Pure browser-bundleable (no node-builtin imports).
 *
 * @connexum/ai-governance  F-NEW-PRODUCT-SANDBOX-REPLAY (player)
 */
import { fromReplayEvent } from './runtime-event-renderer.js';
const DEFAULT_SCHEDULE = (cb, delayMs) => {
    const handle = setTimeout(cb, delayMs);
    return () => clearTimeout(handle);
};
export function createReplayPlayer(sequence, callbacks, options = {}) {
    const speed = options.speedMultiplier ?? 1;
    if (speed <= 0) {
        throw new Error('createReplayPlayer: speedMultiplier must be > 0');
    }
    const startIso = options.startIso ?? new Date().toISOString();
    const schedule = options.schedule ?? DEFAULT_SCHEDULE;
    let started = false;
    let stopped = false;
    let done = false;
    let rowsEmitted = 0;
    const cancellers = [];
    return {
        start() {
            if (started)
                return;
            started = true;
            for (const ev of sequence.events) {
                const delay = ev.tMs / speed;
                const cancel = schedule(() => {
                    if (stopped || done)
                        return;
                    const row = fromReplayEvent(ev, startIso);
                    callbacks.onRow(row);
                    rowsEmitted += 1;
                    if (rowsEmitted === sequence.events.length) {
                        done = true;
                        callbacks.onDone?.({ ok: true, rowsEmitted });
                    }
                }, delay);
                cancellers.push(cancel);
            }
            // If the sequence is empty, fire done immediately.
            if (sequence.events.length === 0) {
                done = true;
                callbacks.onDone?.({ ok: true, rowsEmitted: 0 });
            }
        },
        stop() {
            if (stopped || done)
                return;
            stopped = true;
            for (const c of cancellers)
                c();
            callbacks.onDone?.({ ok: false, rowsEmitted, reason: 'stopped by caller' });
        },
        isPlaying() {
            return started && !done && !stopped;
        },
        isDone() {
            return done;
        },
    };
}
/**
 * Convenience: synchronously realise all rows of a sequence without any
 * scheduling delay. Useful for SSR / pre-render of the demo.
 */
export function realiseSequence(sequence, startIso = '2026-05-12T00:00:00.000Z') {
    return sequence.events.map((ev) => fromReplayEvent(ev, startIso));
}
//# sourceMappingURL=replay-player.js.map