import * as tsplus_module_1 from "@effect/core/stream/Channel/operations/writeChunk";
import * as tsplus_module_2 from "@effect/core/stream/Channel/operations/concatMap";
import * as tsplus_module_3 from "@effect/core/stream/Channel/operations/pipeTo";
import * as tsplus_module_4 from "@effect/core/stream/Channel/operations/runScoped";
import * as tsplus_module_5 from "@effect/core/io/Effect/operations/fork";
import * as tsplus_module_6 from "@effect/core/stream/Stream/operations/_internal/Handoff";
import * as tsplus_module_7 from "@effect/core/io/Effect/operations/do";
import * as tsplus_module_8 from "@effect/core/io/Effect/operations/tap";
import * as tsplus_module_9 from "@effect/core/io/Effect/operations/map";
import * as tsplus_module_10 from "@effect/core/stream/Channel/operations/unwrapScoped";
import * as tsplus_module_11 from "@effect/core/stream/Take/operations/single";
import * as tsplus_module_12 from "@effect/core/stream/Channel/operations/fromEffect";
import * as tsplus_module_13 from "@effect/core/stream/Channel/operations/zipRight";
import * as tsplus_module_14 from "@effect/core/stream/Take/operations/failCause";
import * as tsplus_module_15 from "@effect/core/stream/Take/operations/end";
import * as tsplus_module_16 from "@effect/core/stream/Channel/operations/readWithCause";
import * as tsplus_module_17 from "@effect/core/stream/Channel/operations/unit";
import * as tsplus_module_18 from "@effect/core/stream/Channel/operations/failCause";
import * as tsplus_module_19 from "@effect/core/stream/Channel/operations/write";
import * as tsplus_module_20 from "@effect/core/stream/Take/operations/fold";
import * as tsplus_module_21 from "@effect/core/stream/Channel/operations/flatMap";
import { concreteStream, StreamInternal } from "@effect/core/stream/Stream/operations/_internal/StreamInternal";
/**
 * Combines this stream and the specified stream deterministically using the
 * stream of boolean values `b` to control which stream to pull from next.
 * `true` indicates to pull from this stream and `false` indicates to pull
 * from the specified stream. Only consumes as many elements as requested by
 * `b`. If either this stream or the specified stream are exhausted further
 * requests for values from that stream will be ignored.
 *
 * @tsplus fluent ets/Stream interleaveWith
 */

export function interleaveWith_(self, that, b, __tsplusTrace) {
  void 0;
  return new StreamInternal(tsplus_module_10.unwrapScoped(tsplus_module_9.map_(tsplus_module_8.tap_(tsplus_module_8.tap_(tsplus_module_7.bind_(tsplus_module_7.bind_(tsplus_module_7.Do(), "left", () => tsplus_module_6.make(__tsplusTrace), __tsplusTrace), "right", () => tsplus_module_6.make(__tsplusTrace), __tsplusTrace), ({
    left
  }) => tsplus_module_5.fork(tsplus_module_4.runScoped(tsplus_module_3.pipeTo_(tsplus_module_2.concatMap_(self.channel, tsplus_module_1.writeChunk), () => producer(left, __tsplusTrace))), __tsplusTrace), __tsplusTrace), ({
    right
  }) => {
    const that0 = that();
    void 0;
    return tsplus_module_5.fork(tsplus_module_4.runScoped(tsplus_module_3.pipeTo_(tsplus_module_2.concatMap_(that0.channel, tsplus_module_1.writeChunk), () => producer(right, __tsplusTrace))), __tsplusTrace);
  }, __tsplusTrace), ({
    left,
    right
  }) => {
    const b0 = b();
    void 0;
    return tsplus_module_3.pipeTo_(tsplus_module_2.concatMap_(b0.channel, tsplus_module_1.writeChunk), () => process(left, right, false, false, __tsplusTrace));
  }, __tsplusTrace)));
}
/**
 * Combines this stream and the specified stream deterministically using the
 * stream of boolean values `b` to control which stream to pull from next.
 * `true` indicates to pull from this stream and `false` indicates to pull
 * from the specified stream. Only consumes as many elements as requested by
 * `b`. If either this stream or the specified stream are exhausted further
 * requests for values from that stream will be ignored.
 *
 * @tsplus static ets/Stream/Aspects interleaveWith
 */

export const interleaveWith = (that, b, __tsplusTrace) => self => interleaveWith_(self, that, b, __tsplusTrace);

function producer(handoff, __tsplusTrace) {
  return tsplus_module_16.readWithCause(value => tsplus_module_13.zipRight_(tsplus_module_12.fromEffect(() => tsplus_module_6.offer(handoff, tsplus_module_11.single(value), __tsplusTrace)), () => producer(handoff, __tsplusTrace)), cause => tsplus_module_12.fromEffect(() => tsplus_module_6.offer(handoff, tsplus_module_14.failCause(cause), __tsplusTrace)), () => tsplus_module_12.fromEffect(() => tsplus_module_6.offer(handoff, tsplus_module_15.end, __tsplusTrace)));
}

function process(left, right, leftDone, rightDone, __tsplusTrace) {
  return tsplus_module_16.readWithCause(bool => {
    if (bool && !leftDone) {
      return tsplus_module_21.flatMap_(tsplus_module_12.fromEffect(() => tsplus_module_6.take(left, __tsplusTrace)), take => tsplus_module_20.fold_(take, rightDone ? tsplus_module_17.unit : process(left, right, true, rightDone, __tsplusTrace), cause => tsplus_module_18.failCause(() => cause), chunk => tsplus_module_13.zipRight_(tsplus_module_19.write(() => chunk), () => process(left, right, leftDone, rightDone, __tsplusTrace)), __tsplusTrace));
    }

    if (!bool && !rightDone) {
      return tsplus_module_21.flatMap_(tsplus_module_12.fromEffect(() => tsplus_module_6.take(right, __tsplusTrace)), take => tsplus_module_20.fold_(take, leftDone ? tsplus_module_17.unit : process(left, right, leftDone, true, __tsplusTrace), cause => tsplus_module_18.failCause(() => cause), chunk => tsplus_module_13.zipRight_(tsplus_module_19.write(() => chunk), () => process(left, right, leftDone, rightDone, __tsplusTrace)), __tsplusTrace));
    }

    return process(left, right, leftDone, rightDone, __tsplusTrace);
  }, cause => tsplus_module_18.failCause(() => cause), () => tsplus_module_17.unit);
}
//# sourceMappingURL=interleaveWith.mjs.map