import * as tracing_1 from "../../Tracing"
const fileName_1 = "(@effect-ts/system): _src/Testing/AssertionM/api.ts"
import * as L from "../../Collections/Immutable/List"
import * as T from "../../Effect"
import { pipe } from "../../Function"
import * as O from "../../Option"
import * as AMD from "../AssertionMData"
import * as makeAssertionValue from "../AssertionValue/makeAssertionValue"
import * as BA from "../BoolAlgebra"
import * as BAM from "../BoolAlgebraM"
import * as R from "../Render"
import { apply } from "./apply"
import { AssertionM } from "./AssertionM"
/**
 * Returns a new assertion that succeeds only if both assertions succeed.
 */

export function and(self, that) {
  return new (class extends AssertionM {})(
    () => R.infix(R.param(self), "&&", R.param(that)),
    (actual) => BAM.and_(self.runM(actual), that().runM(actual))
  )
}
/**
 * Returns a new assertion that succeeds if either assertion succeeds.
 */

export function or(self, that) {
  return new (class extends AssertionM {})(
    () => R.infix(R.param(self), "||", R.param(that)),
    (actual) => BAM.or_(self.runM(actual), that().runM(actual))
  )
}
/**
 * Labels this assertion with the specified string.
 */

export function label_(self, str) {
  return apply(() => R.infix(R.param(self), "??", R.param(R.quoted(str))), self.runM)
}
/**
 * Labels this assertion with the specified string.
 */

export function label(str) {
  return (self) => label_(self, str)
}
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */

export function makeAssertionDirect(name, ...params) {
  return (run) => {
    return apply(() => R.function_(name, L.of(L.from(params))), run)
  }
}
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */

export 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
  }
}
/**
 * Makes a new `AssertionM` from a pretty-printing and a function.
 */

export 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()
    }
}
/**
 * Makes a new assertion that negates the specified assertion.
 */

export function not(assertion) {
  return makeAssertionDirect(
    "not",
    R.param(assertion)
  )((_) => BAM.not(assertion.runM(_)))
}
//# sourceMappingURL=api.js.map
