"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.bufferSignal = void 0;
const Tp = __importStar(require("../../../../../Collections/Immutable/Tuple"));
const T = __importStar(require("../../../../../Effect"));
const Function_1 = require("../../../../../Function");
const M = __importStar(require("../../../../../Managed"));
const P = __importStar(require("../../../../../Promise"));
const Q = __importStar(require("../../../../../Queue"));
const Ref = __importStar(require("../../../../../Ref"));
const CH = __importStar(require("../../../Channel"));
const TK = __importStar(require("../../../Take"));
function bufferSignal(managed, channel) {
    const producer = (queue, ref) => {
        const terminate = (take) => CH.fromEffect((T.asUnit(T.tap_(T.tap_(T.tap_(T.bind_(T.tap_(T.bind_(T.do, "latch", () => ref.get), ({ latch }) => P.await(latch)), "p", () => P.make()), ({ p }) => Q.offer_(queue, Tp.tuple(take, p))), ({ p }) => ref.set(p)), ({ p }) => P.await(p)))));
        return CH.readWith((_in) => CH.zipRight_(CH.fromEffect((T.asUnit(T.tap_(T.bind_(T.bind_(T.do, "p", () => P.make()), "added", ({ p }) => Q.offer_(queue, Tp.tuple(TK.chunk(_in), p))), ({ added, p }) => T.when_(ref.set(p), () => added))))), producer(queue, ref)), (err) => terminate(TK.fail(err)), (_) => terminate(TK.end));
    };
    const consumer = (queue) => {
        const process = CH.chain_(CH.fromEffect(Q.take(queue)), ({ tuple: [take, promise] }) => CH.zipRight_(CH.fromEffect(P.succeed_(promise, undefined)), TK.fold_(take, CH.end(undefined), (error) => CH.failCause(error), (value) => CH.zipRight_(CH.write(value), process))));
        return process;
    };
    return CH.managed_((M.map_(M.tap_(M.bind_(M.tap_(M.bind_(M.bind_(M.do, "queue", () => managed), "start", () => T.toManaged(P.make())), ({ start }) => T.toManaged(P.succeed_(start, undefined))), "ref", ({ start }) => Ref.makeManagedRef(start)), ({ queue, ref }) => M.fork(CH.runManaged(channel[">>>"](producer(queue, ref))))), ({ queue }) => queue)), (queue) => consumer(queue));
}
exports.bufferSignal = bufferSignal;
//# sourceMappingURL=bufferSignal.js.map