// AsrSessionController（Phase 1 引擎抽象与 Worker 化；对齐方案 §5）。
// ASR Worker 内的会话管理器：把输入 PCM 分发给当前 ASR 引擎、管理会话生命周期；
// 通过 generation gating 丢弃旧会话产生的 partial/stable/error 事件。
// 模型管理（status/inspect/download/remove/availability/dump）不属控制器职责，
// 由 asr-worker-handler 直接在共享 transcriber 上调用。
import { emptyAsrMetrics } from "./asr-metrics.js";
export class AsrSessionController {
    engine;
    engineKind;
    generation = 0;
    createEngine;
    emit;
    constructor(options) {
        this.createEngine = options.createEngine;
        this.emit = options.emit;
    }
    async start(sourceLanguage, kind) {
        if (this.engine && this.engineKind !== kind) {
            this.engine.dispose();
            this.engine = undefined;
        }
        if (!this.engine) {
            this.engine = this.createEngine(kind);
            this.engineKind = kind;
        }
        const engine = this.engine;
        const generation = ++this.generation;
        const config = {
            sourceLanguage,
            onLanguage: (language) => this.publish({ type: "language", language }, generation),
            onPartial: (text, startMs, endMs) => this.publish({ type: "partial", text, startMs, endMs }, generation),
            onStable: (text, startMs, endMs) => this.publish({ type: "stable", text, startMs, endMs }, generation),
            onError: (error) => this.publish({ type: "error", error: error.code }, generation),
        };
        try {
            await engine.init(config);
        }
        catch (error) {
            if (this.generation === generation)
                this.generation += 1;
            throw error;
        }
    }
    pushAudio(frame) {
        const engine = this.engine;
        if (!engine)
            return;
        if (frame.droppedAudioMs && frame.droppedAudioMs > 0)
            engine.recordDroppedAudio?.(frame.droppedAudioMs);
        const pcm16 = new Int16Array(frame.pcm16);
        engine.pushAudio(pcm16, frame.createdAt);
    }
    reset(reason = "overload") {
        this.engine?.reset(reason);
    }
    setPaused(paused) {
        this.engine?.setPaused(paused);
    }
    idlePause() {
        this.engine?.idlePause();
    }
    resumeFromIdle() {
        this.engine?.resumeFromIdle();
    }
    flush() {
        this.engine?.flush();
    }
    metrics() {
        return this.engine?.metrics() ?? emptyAsrMetrics();
    }
    stop() {
        this.generation += 1;
        const engine = this.engine;
        this.engine = undefined;
        this.engineKind = undefined;
        engine?.dispose();
    }
    publish(event, generation) {
        if (generation === this.generation)
            this.emit(event);
    }
}
