"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.not =
  exports.makeAssertionRecM =
  exports.makeAssertionM =
  exports.makeAssertionDirect =
  exports.label =
  exports.label_ =
  exports.or =
  exports.and =
    void 0
const tracing_1 = __importStar(require("../../Tracing"))
const fileName_1 = "(@effect-ts/system): _src/Testing/AssertionM/api.ts"
const L = __importStar(require("../../Collections/Immutable/List"))
const T = __importStar(require("../../Effect"))
const Function_1 = require("../../Function")
const O = __importStar(require("../../Option"))
const AMD = __importStar(require("../AssertionMData"))
const makeAssertionValue = __importStar(require("../AssertionValue/makeAssertionValue"))
const BA = __importStar(require("../BoolAlgebra"))
const BAM = __importStar(require("../BoolAlgebraM"))
const R = __importStar(require("../Render"))
const apply_1 = require("./apply")
const AssertionM_1 = require("./AssertionM")
/**
 * Returns a new assertion that succeeds only if both assertions succeed.
 */
function and(self, that) {
  return new (class extends AssertionM_1.AssertionM {})(
    () => R.infix(R.param(self), "&&", R.param(that)),
    (actual) => BAM.and_(self.runM(actual), that().runM(actual))
  )
}
exports.and = and
/**
 * Returns a new assertion that succeeds if either assertion succeeds.
 */
function or(self, that) {
  return new (class extends AssertionM_1.AssertionM {})(
    () => R.infix(R.param(self), "||", R.param(that)),
    (actual) => BAM.or_(self.runM(actual), that().runM(actual))
  )
}
exports.or = or
/**
 * Labels this assertion with the specified string.
 */
function label_(self, str) {
  return (0, apply_1.apply)(
    () => R.infix(R.param(self), "??", R.param(R.quoted(str))),
    self.runM
  )
}
exports.label_ = label_
/**
 * Labels this assertion with the specified string.
 */
function label(str) {
  return (self) => label_(self, str)
}
exports.label = label
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */
function makeAssertionDirect(name, ...params) {
  return (run) => {
    return (0, apply_1.apply)(() => R.function_(name, L.of(L.from(params))), run)
  }
}
exports.makeAssertionDirect = makeAssertionDirect
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */
function makeAssertionM(name, ...params) {
  return (run) => {
    const assertion = makeAssertionDirect(
      name,
      ...params
    )((actual) => {
      const actualValue = actual()
      return BAM.chain((p) => {
        const result = () =>
          p
            ? BA.success(
                makeAssertionValue.makeAssertionValue(
                  assertion,
                  () => actualValue,
                  result
                )
              )
            : BA.failure(
                makeAssertionValue.makeAssertionValue(
                  assertion,
                  () => actualValue,
                  result
                )
              )
        return new BAM.BoolAlgebraM(T.succeed(result(), fileName_1 + ":90:48"))
      })(BAM.fromEffect(run(() => actualValue)))
    })
    return assertion
  }
}
exports.makeAssertionM = makeAssertionM
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */
function makeAssertionRecM(name, ...params) {
  return (assertion) =>
    (get, orElse = AMD.asFailureM) => {
      const resultAssertion = () =>
        makeAssertionDirect(
          name,
          ...params
        )((a) => {
          const actualValue = a()
          return BAM.chain((p) => {
            return O.fold_(
              p,
              () =>
                orElse(AMD.makeAssertionMData(resultAssertion(), () => actualValue)),
              (b) => {
                return new BAM.BoolAlgebraM(
                  T.map_(
                    assertion.runM(() => b).run,
                    (p) => {
                      const result = () =>
                        BA.isSuccess(p)
                          ? BA.success(
                              makeAssertionValue.makeAssertionValue(
                                assertion,
                                () => actualValue,
                                result
                              )
                            )
                          : BA.failure(
                              makeAssertionValue.makeAssertionValue(
                                assertion,
                                () => b,
                                () => p
                              )
                            )
                      return result()
                    },
                    fileName_1 + ":127:28"
                  )
                )
              }
            )
          })(BAM.fromEffect(get(() => actualValue)))
        })
      return resultAssertion()
    }
}
exports.makeAssertionRecM = makeAssertionRecM
/**
 * Makes a new assertion that negates the specified assertion.
 */
function not(assertion) {
  return makeAssertionDirect(
    "not",
    R.param(assertion)
  )((_) => BAM.not(assertion.runM(_)))
}
exports.not = not
//# sourceMappingURL=api.js.map
