"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MsgChainUtil = void 0;
const utils_1 = require("@streamr/utils");
const PushBuffer_1 = require("./../utils/PushBuffer");
class MsgChainProcessor {
    busy = new utils_1.Gate(true);
    inputBuffer = [];
    outputBuffer;
    processMessageFn;
    onError;
    constructor(outputBuffer, processMessageFn, onError) {
        this.outputBuffer = outputBuffer;
        this.processMessageFn = processMessageFn;
        this.onError = onError;
    }
    async addMessage(message) {
        this.inputBuffer.push(message);
        if (this.busy.isOpen()) {
            this.busy.close();
            while (this.inputBuffer.length > 0) {
                const nextMessage = this.inputBuffer.shift();
                try {
                    const processedMessage = await this.processMessageFn(nextMessage);
                    this.outputBuffer.push(processedMessage);
                }
                catch (e) {
                    this.onError.trigger(e);
                }
            }
            this.busy.open();
        }
    }
}
class MsgChainUtil {
    outputBuffer = new PushBuffer_1.PushBuffer();
    processors = new Map();
    processMessageFn;
    onError;
    constructor(processMessageFn, onError) {
        this.processMessageFn = processMessageFn;
        this.onError = onError;
    }
    addMessage(message) {
        const id = `${message.getPublisherId()}-${message.getMsgChainId()}`;
        let processor = this.processors.get(id);
        if (processor === undefined) {
            processor = new MsgChainProcessor(this.outputBuffer, this.processMessageFn, this.onError);
            this.processors.set(id, processor);
        }
        processor.addMessage(message); // add a task, but don't wait for it to complete
    }
    async flush() {
        await Promise.all(Array.from(this.processors.values()).map((p) => p.busy.waitUntilOpen()));
    }
    stop(err) {
        this.outputBuffer.endWrite(err);
    }
    [Symbol.asyncIterator]() {
        return this.outputBuffer;
    }
}
exports.MsgChainUtil = MsgChainUtil;
//# sourceMappingURL=MsgChainUtil.js.map