"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.none =
  exports.fibersIn =
  exports.track =
  exports.trackMainFibers =
  exports.mainFibers =
  exports._continue =
  exports._stop =
  exports.propagationOr =
  exports.propagationAnd =
  exports.Continue =
  exports.Stop =
  exports.Supervisor =
    void 0
// tracing: off
/**
 * Ported from https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/Supervisor.scala
 *
 * Copyright 2020 Michael Arnaldi and the Matechs Garage Contributors.
 */
require("../Operator")
const SS = __importStar(require("../Collections/Immutable/SortedSet"))
const core_1 = require("../Effect/core")
const zip_1 = require("../Effect/zip")
const runtimeOrd_1 = require("../Fiber/runtimeOrd")
const AtomicReference_1 = require("../Support/AtomicReference")
/**
 * A `Supervisor<A>` is allowed to supervise the launching and termination of
 * fibers, producing some visible value of type `A` from the supervision.
 */
class Supervisor {
  constructor(value, unsafeOnStart, unsafeOnEnd) {
    this.value = value
    this.unsafeOnStart = unsafeOnStart
    this.unsafeOnEnd = unsafeOnEnd
  }
  /**
   * Returns a new supervisor that performs the function of this supervisor,
   * and the function of the specified supervisor, producing a tuple of the
   * outputs produced by both supervisors.
   *
   * The composite supervisor indicates that it has fully handled the
   * supervision event if only both component supervisors indicate they have
   * handled the supervision event.
   */
  and(that) {
    return new Supervisor(
      (0, zip_1.zip_)(this.value, that.value),
      (environment, effect, parent, fiber) =>
        (0, exports.propagationAnd)(
          this.unsafeOnStart(environment, effect, parent, fiber),
          that.unsafeOnStart(environment, effect, parent, fiber)
        ),
      (value, fiber) =>
        (0, exports.propagationAnd)(
          this.unsafeOnEnd(value, fiber),
          that.unsafeOnEnd(value, fiber)
        )
    )
  }
  /**
   * Returns a new supervisor that performs the function of this supervisor,
   * and the function of the specified supervisor, producing a tuple of the
   * outputs produced by both supervisors.
   *
   * The composite supervisor indicates that it has fully handled the
   * supervision event if either component supervisors indicate they have
   * handled the supervision event.
   */
  or(that) {
    return new Supervisor(
      (0, zip_1.zip_)(this.value, that.value),
      (environment, effect, parent, fiber) =>
        (0, exports.propagationOr)(
          this.unsafeOnStart(environment, effect, parent, fiber),
          that.unsafeOnStart(environment, effect, parent, fiber)
        ),
      (value, fiber) =>
        (0, exports.propagationOr)(
          this.unsafeOnEnd(value, fiber),
          that.unsafeOnEnd(value, fiber)
        )
    )
  }
}
exports.Supervisor = Supervisor
/**
 * A hint indicating supervision events no longer require propagation.
 */
class Stop {
  constructor() {
    this._tag = "Stop"
  }
}
exports.Stop = Stop
/**
 * A hint indicating supervision events require further propagation.
 */
class Continue {
  constructor() {
    this._tag = "Continue"
  }
}
exports.Continue = Continue
const propagationAnd = (self, that) =>
  self._tag === "Continue" && that._tag === "Continue"
    ? exports._continue
    : exports._stop
exports.propagationAnd = propagationAnd
const propagationOr = (self, that) =>
  self._tag === "Continue" || that._tag === "Continue"
    ? exports._continue
    : exports._stop
exports.propagationOr = propagationOr
exports._stop = new Stop()
exports._continue = new Continue()
exports.mainFibers = new Set()
function unsafeTrackMain() {
  const interval = new AtomicReference_1.AtomicReference(undefined)
  return new Supervisor(
    (0, core_1.succeedWith)(() => exports.mainFibers),
    (_, __, ___, fiber) => {
      if (exports.mainFibers.has(fiber)) {
        if (typeof interval.get === "undefined") {
          interval.set(
            setInterval(() => {
              // keep process alive
            }, 60000)
          )
        }
      }
      return exports._continue
    },
    (_, fiber) => {
      exports.mainFibers.delete(fiber)
      if (exports.mainFibers.size === 0) {
        const ci = interval.get
        if (ci) {
          clearInterval(ci)
        }
      }
      return exports._continue
    }
  )
}
exports.trackMainFibers = unsafeTrackMain()
/**
 * Creates a new supervisor that tracks children in a set.
 */
exports.track = (0, core_1.suspend)(() =>
  fibersIn(
    new AtomicReference_1.AtomicReference(SS.make((0, runtimeOrd_1.runtimeOrd)()))
  )
)
/**
 * Creates a new supervisor that tracks children in a set.
 */
function fibersIn(ref) {
  return (0, core_1.succeedWith)(
    () =>
      new Supervisor(
        (0, core_1.succeedWith)(() => ref.get),
        (_, __, ___, fiber) => {
          ref.set(SS.add_(ref.get, fiber))
          return exports._continue
        },
        (_, fiber) => {
          ref.set(SS.remove_(ref.get, fiber))
          return exports._continue
        }
      )
  )
}
exports.fibersIn = fibersIn
/**
 * A supervisor that doesn't do anything in response to supervision events.
 */
exports.none = new Supervisor(
  core_1.unit,
  () => exports._continue,
  () => exports._continue
)
//# sourceMappingURL=index.js.map
