"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.repeatWith = void 0
const Function_1 = require("../../Function")
const O = __importStar(require("../../Option"))
const SC = __importStar(require("../../Schedule"))
const T = __importStar(require("../_internal/effect"))
const M = __importStar(require("../_internal/managed"))
const Ref = __importStar(require("../_internal/ref"))
const Pull = __importStar(require("./../Pull"))
const concat_1 = require("./concat")
const definitions_1 = require("./definitions")
const fromEffect_1 = require("./fromEffect")
const map_1 = require("./map")
/**
 * Repeats the entire stream using the specified schedule. The stream will execute normally,
 * and then repeat again according to the provided schedule. The schedule output will be emitted at
 * the end of each repetition and can be unified with the stream elements using the provided functions.
 */
function repeatWith(schedule) {
  return (f, g) => (self) =>
    new definitions_1.Stream(
      M.map_(
        M.let_(
          M.bind_(
            M.bind_(
              M.bind_(
                M.bind_(M.do, "sdriver", () => T.toManaged(SC.driver(schedule))),
                "switchPull",
                () => M.switchable()
              ),
              "currPull",
              ({ switchPull }) =>
                T.toManaged(
                  T.chain_(switchPull((0, map_1.map_)(self, f).proc), Ref.makeRef)
                )
            ),
            "doneRef",
            () => T.toManaged(Ref.makeRef(false))
          ),
          "pull",
          ({ currPull, doneRef, sdriver, switchPull }) => {
            const go = T.chain_(doneRef.get, (done) => {
              if (done) {
                return Pull.end
              } else {
                return T.foldM_(
                  T.flatten(currPull.get),
                  O.fold(
                    () => {
                      const scheduleOutput = T.map_(T.orDie(sdriver.last), g)
                      const continue_ = T.zipRight_(
                        T.tap_(
                          T.zipRight_(
                            sdriver.next(undefined),
                            switchPull(
                              (0, concat_1.concat_)(
                                (0, map_1.map_)(self, f),
                                (0, fromEffect_1.fromEffect)(scheduleOutput)
                              ).proc
                            )
                          ),
                          (_) => currPull.set(_)
                        ),
                        go
                      )
                      const halt = T.zipRight_(doneRef.set(true), Pull.end)
                      return T.orElse_(continue_, () => halt)
                    },
                    (e) => T.fail(O.some(e))
                  ),
                  (_) => T.succeed(_)
                )
              }
            })
            return go
          }
        ),
        ({ pull }) => pull
      )
    )
}
exports.repeatWith = repeatWith
//# sourceMappingURL=repeatWith.js.map
