'use strict';

var choreoDSL = require('./choreoDSL.js');

class ScoreBus {
    constructor() {
        this.target = new EventTarget();
    }
    push(score) {
        const e = { score, at: Date.now() };
        this.target.dispatchEvent(new CustomEvent("score", { detail: e }));
    }
    subscribe(handler) {
        const wrap = (ev) => handler(ev.detail);
        this.target.addEventListener("score", wrap);
        return () => this.target.removeEventListener("score", wrap);
    }
}
/** Shared score event bus. */
const scoreBus = new ScoreBus();
/** Subscribe to score events with throttling + dedup. */
function onScore(handler, opts = {}) {
    var _a, _b, _c;
    const min = (_a = opts.minIntervalMs) !== null && _a !== void 0 ? _a : 400;
    const dedupe = (_b = opts.dedupeWindowMs) !== null && _b !== void 0 ? _b : 800;
    const roundTo = Math.max(0, Math.floor((_c = opts.roundTo) !== null && _c !== void 0 ? _c : 1));
    let lastEventAt = 0;
    let lastRounded = null;
    let lastRoundedAt = 0;
    return scoreBus.subscribe((e) => {
        const now = e.at;
        if (now - lastEventAt < min)
            return;
        lastEventAt = now;
        const factor = Math.pow(10, roundTo);
        const rounded = (Math.round(e.score * factor) / factor).toFixed(roundTo);
        if (lastRounded && rounded === lastRounded && now - lastRoundedAt < dedupe)
            return;
        lastRounded = rounded;
        lastRoundedAt = now;
        handler(e.score);
    });
}
/** Map a score to a reaction choreography. */
function reactionForScore(score, rng = Math.random) {
    const r = rng();
    if (score >= 8.5) {
        const strong = [
            choreoDSL.seq().happy(300).celebrate(600),
            choreoDSL.seq().danceA(300).danceB(300).celebrate(500),
            choreoDSL.seq().jump(400).raiseCard(score, 700),
        ];
        return strong[Math.floor(r * strong.length)];
    }
    if (score >= 5.5) {
        const mid = [
            choreoDSL.seq().shrug(450),
            choreoDSL.seq().nodYes(450),
            choreoDSL.seq().leanBack(400),
        ];
        return mid[Math.floor(r * mid.length)].raiseCard(score, 700);
    }
    const low = [
        choreoDSL.seq().angry(400).shouting(400),
        choreoDSL.seq().facepalm(500).disappointed(400),
        choreoDSL.seq().swearing(450).shakeNo(450),
    ];
    return low[Math.floor(r * low.length)].raiseCard(score, 900);
}
/** Play intro choreography for actors. */
async function playIntro(actors) {
    if (!actors.length)
        return;
    const programs = [
        choreoDSL.seq().enterFromLeft(0.6).waveHand(600).raiseCard(9, 700).idle(200),
        choreoDSL.seq().enterFromRight(0.6).spin(600).danceA(400).idle(200),
        choreoDSL.seq().enterFromLeft(0.5).jump(450).pointRight(350).idle(200),
        choreoDSL.seq().enterFromRight(0.5).happy(300).raiseCard(10, 800),
    ];
    await choreoDSL.runRounds(actors, programs);
}
/** Emit a score event for testing. */
const simulateScore = (score) => scoreBus.push(score);
/** Attach score reactions to actors. */
function attachScoreReactions(actors, opts = {}, rng = Math.random) {
    return onScore(async (score) => {
        const programs = actors.map(() => reactionForScore(score, rng));
        await choreoDSL.runRounds(actors, programs, 80, { score });
    }, opts);
}

exports.attachScoreReactions = attachScoreReactions;
exports.onScore = onScore;
exports.playIntro = playIntro;
exports.reactionForScore = reactionForScore;
exports.scoreBus = scoreBus;
exports.simulateScore = simulateScore;
//# sourceMappingURL=karaokeIntegration.js.map
