import { wait } from "alcalzone-shared/async";
import { ZWaveSerialStreamFactory, } from "../serialport/ZWaveSerialStream.js";
export class MockPort {
    constructor() {
        const { readable, writable: sink } = new TransformStream();
        this.#sink = sink;
        this.readable = readable;
    }
    /** How long each write operation should take */
    writeDelay = 0;
    // Remembers the last written data
    lastWrite;
    // Internal stream to allow emitting data from the port
    #sourceController;
    // Public readable stream to allow handling the written data
    #sink;
    /** Exposes the data written by the host as a readable stream */
    readable;
    factory() {
        return () => {
            let writer;
            const sink = {
                write: async (chunk, _controller) => {
                    // Remember the last written data
                    this.lastWrite = chunk;
                    // Only write to the sink if its readable side has a reader attached.
                    // Otherwise, we get backpressure on the writable side of the mock port
                    if (this.readable.locked) {
                        writer ??= this.#sink.getWriter();
                        // Simulate a slow write if necessary
                        if (this.writeDelay > 0) {
                            await wait(this.writeDelay);
                        }
                        // This will finish immediately on the mock port
                        await writer.write(chunk);
                    }
                },
                close: () => {
                    writer?.releaseLock();
                },
            };
            const source = {
                start: (controller) => {
                    this.#sourceController = controller;
                },
            };
            return Promise.resolve({ sink, source });
        };
    }
    emitData(data) {
        this.#sourceController?.enqueue(data);
    }
    destroy() {
        try {
            this.#sourceController?.close();
            this.#sourceController = undefined;
        }
        catch {
            // Ignore - the controller might already be closed
        }
    }
}
export async function createAndOpenMockedZWaveSerialPort() {
    const port = new MockPort();
    const factory = new ZWaveSerialStreamFactory(port.factory(), (await import("#default_bindings/log")).log({
        enabled: false,
    }));
    const serial = await factory.createStream();
    return { port, serial };
}
//# sourceMappingURL=MockPort.js.map