"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.raceFirst =
  exports.raceFirst_ =
  exports.raceEither =
  exports.raceEither_ =
  exports.race =
  exports.race_ =
    void 0
// tracing: off
const Cause = __importStar(require("../Cause/core"))
const E = __importStar(require("../Either"))
const Exit = __importStar(require("../Exit/api"))
const Fiber = __importStar(require("../Fiber/core"))
const Function_1 = require("../Function")
const core = __importStar(require("./core"))
const core_scope_1 = require("./core-scope")
const done_1 = require("./done")
const map_1 = require("./map")
const mapErrorCause_1 = require("./mapErrorCause")
function mergeInterruption(a) {
  return (x) => {
    switch (x._tag) {
      case "Success": {
        return core.succeed(a)
      }
      case "Failure": {
        return Cause.interruptedOnly(x.cause) ? core.succeed(a) : core.halt(x.cause)
      }
    }
  }
}
/**
 * Returns an effect that races this effect with the specified effect,
 * returning the first successful `A` from the faster side. If one effect
 * succeeds, the other will be interrupted. If neither succeeds, then the
 * effect will fail with some error.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated. If early return is
 * desired
 */
function race_(self, that, __trace) {
  return core.descriptorWith((d) =>
    (0, core_scope_1.raceWith_)(
      self,
      that,
      (exit, right) =>
        Exit.foldM_(
          exit,
          (cause) =>
            (0, mapErrorCause_1.mapErrorCause_)(Fiber.join(right), (_) =>
              Cause.both(cause, _)
            ),
          (a) => core.chain_(right.interruptAs(d.id), mergeInterruption(a))
        ),
      (exit, left) =>
        Exit.foldM_(
          exit,
          (cause) =>
            (0, mapErrorCause_1.mapErrorCause_)(Fiber.join(left), (_) =>
              Cause.both(_, cause)
            ),
          (a) => core.chain_(left.interruptAs(d.id), mergeInterruption(a))
        ),
      __trace
    )
  )
}
exports.race_ = race_
/**
 * Returns an effect that races this effect with the specified effect,
 * returning the first successful `A` from the faster side. If one effect
 * succeeds, the other will be interrupted. If neither succeeds, then the
 * effect will fail with some error.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated.
 *
 * @dataFirst race_
 */
function race(that, __trace) {
  return (self) => race_(self, that, __trace)
}
exports.race = race
/**
 * Returns an effect that races this effect with the specified effect,
 * yielding the first result to succeed. If neither effect succeeds, then the
 * composed effect will fail with some error.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated.
 */
function raceEither_(self, that, __trace) {
  return race_((0, map_1.map_)(self, E.left), (0, map_1.map_)(that, E.right), __trace)
}
exports.raceEither_ = raceEither_
/**
 * Returns an effect that races this effect with the specified effect,
 * yielding the first result to succeed. If neither effect succeeds, then the
 * composed effect will fail with some error.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated.
 *
 * @dataFirst raceEither_
 */
function raceEither(that, __trace) {
  return (self) => raceEither_(self, that, __trace)
}
exports.raceEither = raceEither
/**
 * Returns an effect that races this effect with the specified effect,
 * yielding the first result to complete, whether by success or failure. If
 * neither effect completes, then the composed effect will not complete.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated. If early return is
 * desired, then instead of performing `l raceFirst r`, perform
 * `l.disconnect raceFirst r.disconnect`, which disconnects left and right
 * interrupt signal, allowing a fast return, with interruption performed
 * in the background.
 */
function raceFirst_(self, that, __trace) {
  return core.chain_(race_(core.result(self), core.result(that), __trace), (a) =>
    (0, done_1.done)(a)
  )
}
exports.raceFirst_ = raceFirst_
/**
 * Returns an effect that races this effect with the specified effect,
 * yielding the first result to complete, whether by success or failure. If
 * neither effect completes, then the composed effect will not complete.
 *
 * WARNING: The raced effect will safely interrupt the "loser", but will not
 * resume until the loser has been cleanly terminated. If early return is
 * desired, then instead of performing `l raceFirst r`, perform
 * `l.disconnect raceFirst r.disconnect`, which disconnects left and right
 * interrupt signal, allowing a fast return, with interruption performed
 * in the background.
 *
 * @dataFirst raceFirst_
 */
function raceFirst(that, __trace) {
  return (self) => raceFirst_(self, that, __trace)
}
exports.raceFirst = raceFirst
//# sourceMappingURL=race.js.map
