import * as tracing_1 from "../../Tracing";
const fileName_1 = "(@effect-ts/system): _src/Testing/Api/index.ts";
import * as List from "../../Collections/Immutable/List";
import * as T from "../../Effect";
import { SourceLocation } from "../../Fiber";
import { pipe } from "../../Function";
import * as M from "../../Managed";
import * as O from "../../Option";
import * as makeAssertionValue from "../AssertionValue/makeAssertionValue";
import * as sameAssertion_ from "../AssertionValue/sameAssertion";
import * as BA from "../BoolAlgebra";
import { FailureDetails } from "../FailureDetails";
import * as Spec from "../Spec";
import * as TA from "../TestAnnotation";
import { TestAnnotationMap } from "../TestAnnotationMap";
import * as TF from "../TestFailure";
import * as TS from "../TestSuccess";
export function test(label, __trace) {
  return assertion => testM(label, __trace)(() => T.succeedWith(assertion, fileName_1 + ":24:46"));
}
export function testM(label, __trace) {
  return assertion => Spec.annotate(TA.location, __trace ? List.of(new SourceLocation(__trace)) : List.empty())(Spec.test(label, ZTest(assertion), TestAnnotationMap.empty));
}
export function suite(label) {
  return (...tests) => Spec.suite(label, M.succeed(tests, fileName_1 + ":44:35"), O.none);
}

function ZTest(assertion) {
  return T.foldCauseM_(T.suspend(assertion, fileName_1 + ":51:14"), c => T.fail(TF.halt(c), fileName_1 + ":53:20"), r => O.fold_(BA.failures(r), () => T.succeed(new TS.Succeeded(BA.unit), fileName_1 + ":57:26"), failures => T.fail(TF.assertion(failures), fileName_1 + ":58:31")), fileName_1 + ":52:17");
}

export function assert(value, expression = O.none, sourceLocation = O.none) {
  return assertion => traverseResult(() => value, assertion.run(() => value), assertion, expression, sourceLocation);
}

function traverseResult(value, assertResult, assertion, expression, sourceLocation) {
  return BA.chain(fragment => {
    function loop(whole, failureDetails) {
      if (sameAssertion_.sameAssertion_(whole, failureDetails.assertion[0])) {
        return BA.success(failureDetails);
      }

      const fragment = whole.result();
      const result = BA.isSuccess(fragment) ? fragment : fragment["!"];
      return BA.chain_(result, fragment => loop(fragment, new FailureDetails([whole, ...failureDetails.assertion])));
    }

    return loop(fragment, new FailureDetails([makeAssertionValue.makeAssertionValue(assertion, value, () => assertResult, expression, sourceLocation)]));
  })(assertResult);
}
//# sourceMappingURL=index.js.map