import * as tracing_1 from "../../../Tracing"
const fileName_1 =
  "(@effect-ts/system): _src/Experimental/Stream/_internal/BufferedPull.ts"
import * as A from "../../../Collections/Immutable/Chunk"
import * as Tp from "../../../Collections/Immutable/Tuple"
import * as T from "../../../Effect"
import { pipe } from "../../../Function"
import * as O from "../../../Option"
import * as Ref from "../../../Ref"
import * as Pull from "./Pull"
export class BufferedPull {
  constructor(upstream, done, cursor) {
    this.upstream = upstream
    this.done = done
    this.cursor = cursor
  }
}
export function make(upstream) {
  return T.map_(
    T.bind_(
      T.bind_(T.do, "done", () => Ref.makeRef(false), fileName_1 + ":20:11"),
      "cursor",
      () => Ref.makeRef(Tp.tuple(A.empty(), 0)),
      fileName_1 + ":21:11"
    ),
    ({ cursor, done }) => new BufferedPull(upstream, done, cursor),
    fileName_1 + ":22:10"
  )
}
export function ifNotDone_(self, fa) {
  return T.chain_(
    Ref.get(self.done),
    (_) => {
      if (_) {
        return Pull.end
      } else {
        return fa
      }
    },
    fileName_1 + ":30:18"
  )
}
/**
 * @dataFirst ifNotDone_
 */

export function ifNotDone(fa) {
  return (self) => ifNotDone_(self, fa)
}
export function update(self) {
  return ifNotDone_(
    self,
    T.foldM_(
      self.upstream,
      O.fold(
        () => T.zipRight_(Ref.set_(self.done, true), Pull.end, fileName_1 + ":54:26"),
        (e) => Pull.fail(e)
      ),
      (chunk) => Ref.set_(self.cursor, Tp.tuple(chunk, 0)),
      fileName_1 + ":51:13"
    )
  )
}
export function pullElement(self) {
  return ifNotDone_(
    self,
    T.flatten(
      Ref.modify_(self.cursor, ({ tuple: [chunk, idx] }) => {
        if (idx >= A.size(chunk)) {
          return Tp.tuple(
            T.zipRight_(update(self), pullElement(self), fileName_1 + ":72:24"),
            Tp.tuple(A.empty(), 0)
          )
        } else {
          return Tp.tuple(
            T.succeed(A.unsafeGet_(chunk, idx), fileName_1 + ":77:22"),
            Tp.tuple(A.empty(), idx + 1)
          )
        }
      }),
      fileName_1 + ":82:16"
    )
  )
}
export function pullChunk(self) {
  return ifNotDone_(
    self,
    T.flatten(
      Ref.modify_(self.cursor, ({ tuple: [chunk, idx] }) => {
        if (idx >= A.size(chunk)) {
          return Tp.tuple(
            T.zipRight_(update(self), pullChunk(self), fileName_1 + ":97:24"),
            Tp.tuple(A.empty(), 0)
          )
        } else {
          return Tp.tuple(
            T.succeed(A.drop_(chunk, idx), fileName_1 + ":101:36"),
            Tp.tuple(A.empty(), 0)
          )
        }
      }),
      fileName_1 + ":104:16"
    )
  )
}
//# sourceMappingURL=BufferedPull.js.map
