// tracing: off
import * as A from "../../Collections/Immutable/Chunk"
import * as Tp from "../../Collections/Immutable/Tuple"
import { pipe } from "../../Function"
import * as O from "../../Option"
import * as T from "../_internal/effect"
import * as M from "../_internal/managed"
import * as Ref from "../_internal/ref"
import * as Pull from "../Pull"
import { Stream } from "./definitions"
/**
 * Zips each element with the next element if present.
 */

export function zipWithNext(self) {
  return new Stream(
    M.map_(
      M.let_(
        M.let_(
          M.bind_(
            M.bind_(M.do, "chunks", () => self.proc),
            "ref",
            () => T.toManaged(Ref.makeRef(O.none))
          ),
          "last",
          ({ ref }) =>
            T.map_(
              T.map_(T.some(Ref.getAndSet_(ref, O.none)), (_) => Tp.tuple(_, O.none)),
              A.single
            )
        ),
        "pull",
        ({ chunks, ref }) => {
          return T.map_(
            T.bind_(
              T.tap_(
                T.let_(
                  T.bind_(
                    T.bind_(T.do, "prev", () => ref.get),
                    "chunk",
                    () => chunks
                  ),
                  "sc",
                  ({ chunk, prev }) =>
                    A.mapAccum_(chunk, prev, (prev, curr) =>
                      Tp.tuple(
                        O.some(curr),
                        O.map_(prev, (_) => Tp.tuple(_, curr))
                      )
                    )
                ),
                ({ sc }) => ref.set(sc.get(0))
              ),
              "result",
              ({ sc }) =>
                Pull.emitChunk(
                  A.filterMap_(
                    sc.get(1),
                    O.fold(
                      () => O.none,
                      ({ tuple: [prev, curr] }) => O.some(Tp.tuple(prev, O.some(curr)))
                    )
                  )
                )
            ),
            ({ result }) => result
          )
        }
      ),
      ({ last, pull }) => T.orElseOptional_(pull, () => last)
    )
  )
}
//# sourceMappingURL=zipWithNext.js.map
