import { decodeTerminalSnapshotPayload, encodeTerminalResizePayload, encodeTerminalStreamFrame, TerminalStreamOpcode, } from "../shared/binary-frames/index.js";
export class TerminalStreamRouter {
    constructor() {
        this.terminalSlots = new Map();
        this.slotTerminals = new Map();
        this.listeners = new Set();
    }
    onEvent(handler) {
        this.listeners.add(handler);
        return () => {
            this.listeners.delete(handler);
        };
    }
    setSlot(terminalId, slot) {
        const existingTerminalId = this.slotTerminals.get(slot);
        if (existingTerminalId && existingTerminalId !== terminalId) {
            this.terminalSlots.delete(existingTerminalId);
        }
        const existingSlot = this.terminalSlots.get(terminalId);
        if (typeof existingSlot === "number" && existingSlot !== slot) {
            this.slotTerminals.delete(existingSlot);
        }
        this.terminalSlots.set(terminalId, slot);
        this.slotTerminals.set(slot, terminalId);
    }
    removeTerminal(terminalId) {
        const slot = this.terminalSlots.get(terminalId);
        if (typeof slot !== "number") {
            return;
        }
        this.terminalSlots.delete(terminalId);
        if (this.slotTerminals.get(slot) === terminalId) {
            this.slotTerminals.delete(slot);
        }
    }
    clearSlots() {
        this.terminalSlots.clear();
        this.slotTerminals.clear();
    }
    encodeInput(terminalId, message) {
        const slot = this.terminalSlots.get(terminalId);
        if (typeof slot !== "number") {
            return null;
        }
        if (message.type === "input") {
            return encodeTerminalStreamFrame({
                opcode: TerminalStreamOpcode.Input,
                slot,
                payload: message.data,
            });
        }
        if (message.type === "resize") {
            return encodeTerminalStreamFrame({
                opcode: TerminalStreamOpcode.Resize,
                slot,
                payload: encodeTerminalResizePayload({
                    rows: message.rows,
                    cols: message.cols,
                }),
            });
        }
        return null;
    }
    handleFrame(frame) {
        const terminalId = this.slotTerminals.get(frame.slot);
        if (!terminalId) {
            return;
        }
        if (frame.opcode === TerminalStreamOpcode.Output) {
            this.emit({
                terminalId,
                type: "output",
                data: frame.payload,
            });
            return;
        }
        if (frame.opcode === TerminalStreamOpcode.Snapshot) {
            const state = decodeTerminalSnapshotPayload(frame.payload);
            if (!state) {
                return;
            }
            this.emit({
                terminalId,
                type: "snapshot",
                state,
            });
        }
    }
    emit(event) {
        for (const listener of this.listeners) {
            try {
                listener(event);
            }
            catch {
                // no-op
            }
        }
    }
}
//# sourceMappingURL=terminal-stream-router.js.map