import { must } from "../../../shared/src/must.js";
/**
 * Forks a stream into multiple streams.
 * Is meant to be paired with a `FanIn` operator which will
 * later merge the forks back together.
 */
export class FanOut {
    #input;
    #outputs = [];
    #fanIn;
    #destroyCount = 0;
    constructor(input) {
        this.#input = input;
        input.setFilterOutput(this);
    }
    setFanIn(fanIn) {
        this.#fanIn = fanIn;
    }
    setFilterOutput(output) {
        this.#outputs.push(output);
    }
    destroy() {
        if (this.#destroyCount < this.#outputs.length) {
            ++this.#destroyCount;
            if (this.#destroyCount === this.#outputs.length) {
                this.#input.destroy();
            }
        }
        else {
            throw new Error('FanOut already destroyed once for each output');
        }
    }
    getSchema() {
        return this.#input.getSchema();
    }
    filter(node, cleanup) {
        let result = false;
        for (const output of this.#outputs) {
            result = output.filter(node, cleanup) || result;
            // Cleanup needs to be forwarded to all outputs, don't short circuit
            // cleanup.  For non-cleanup we can short-circuit on first true.
            if (!cleanup && result) {
                return true;
            }
        }
        return result;
    }
    push(change) {
        for (const out of this.#outputs) {
            out.push(change, this);
        }
        must(this.#fanIn, 'fan-out must have a corresponding fan-in set!').fanOutDonePushingToAllBranches(change.type);
    }
}
//# sourceMappingURL=fan-out.js.map