// Generated by purs version 0.12.5
"use strict";
var Control_Applicative = require("../Control.Applicative/index.js");
var Control_Bind = require("../Control.Bind/index.js");
var Control_Monad_Rec_Class = require("../Control.Monad.Rec.Class/index.js");
var Data_Boolean = require("../Data.Boolean/index.js");
var Data_Eq = require("../Data.Eq/index.js");
var Data_Foldable = require("../Data.Foldable/index.js");
var Data_Function = require("../Data.Function/index.js");
var Data_List_Types = require("../Data.List.Types/index.js");
var Data_Maybe = require("../Data.Maybe/index.js");
var Data_Maybe_First = require("../Data.Maybe.First/index.js");
var Data_Monoid = require("../Data.Monoid/index.js");
var Data_Ord = require("../Data.Ord/index.js");
var Data_Semigroup = require("../Data.Semigroup/index.js");
var Data_Show = require("../Data.Show/index.js");
var Data_Unfoldable = require("../Data.Unfoldable/index.js");
var Effect = require("../Effect/index.js");
var Effect_Console = require("../Effect.Console/index.js");
var Effect_Exception = require("../Effect.Exception/index.js");
var Random_LCG = require("../Random.LCG/index.js");
var Test_QuickCheck_Arbitrary = require("../Test.QuickCheck.Arbitrary/index.js");
var Test_QuickCheck_Gen = require("../Test.QuickCheck.Gen/index.js");
var Success = (function () {
    function Success() {

    };
    Success.value = new Success();
    return Success;
})();
var Failed = (function () {
    function Failed(value0) {
        this.value0 = value0;
    };
    Failed.create = function (value0) {
        return new Failed(value0);
    };
    return Failed;
})();
var Testable = function (test) {
    this.test = test;
};
var withHelp = function (v) {
    return function (v1) {
        if (v) {
            return Success.value;
        };
        if (!v) {
            return new Failed(v1);
        };
        throw new Error("Failed pattern match at Test.QuickCheck (line 187, column 1 - line 187, column 40): " + [ v.constructor.name, v1.constructor.name ]);
    };
};
var testableResult = new Testable(Control_Applicative.pure(Test_QuickCheck_Gen.applicativeGen));
var testableBoolean = new Testable(function (v) {
    if (v) {
        return Control_Applicative.pure(Test_QuickCheck_Gen.applicativeGen)(Success.value);
    };
    if (!v) {
        return Control_Applicative.pure(Test_QuickCheck_Gen.applicativeGen)(new Failed("Test returned false"));
    };
    throw new Error("Failed pattern match at Test.QuickCheck (line 163, column 1 - line 163, column 45): " + [ v.constructor.name ]);
});
var test = function (dict) {
    return dict.test;
};
var testableFunction = function (dictArbitrary) {
    return function (dictTestable) {
        return new Testable(function (f) {
            return Control_Bind.bind(Test_QuickCheck_Gen.bindGen)(Test_QuickCheck_Arbitrary.arbitrary(dictArbitrary))(function ($54) {
                return test(dictTestable)(f($54));
            });
        });
    };
};
var testableGen = function (dictTestable) {
    return new Testable(Data_Function.flip(Control_Bind.bind(Test_QuickCheck_Gen.bindGen))(test(dictTestable)));
};
var showResult = new Data_Show.Show(function (v) {
    if (v instanceof Success) {
        return "Success";
    };
    if (v instanceof Failed) {
        return "Failed: " + v.value0;
    };
    throw new Error("Failed pattern match at Test.QuickCheck (line 176, column 1 - line 176, column 35): " + [ v.constructor.name ]);
});
var quickCheckWithSeed = function (dictTestable) {
    return function (initialSeed) {
        return function (n) {
            return function (prop) {
                var loop = function (v) {
                    if (v.index === n) {
                        return new Control_Monad_Rec_Class.Done(v);
                    };
                    if (Data_Boolean.otherwise) {
                        var v1 = Test_QuickCheck_Gen.runGen(test(dictTestable)(prop))({
                            newSeed: v.seed,
                            size: 10
                        });
                        if (v1.value0 instanceof Success) {
                            return new Control_Monad_Rec_Class.Loop({
                                seed: v1.value1.newSeed,
                                index: v.index + 1 | 0,
                                successes: v.successes + 1 | 0,
                                firstFailure: v.firstFailure
                            });
                        };
                        if (v1.value0 instanceof Failed) {
                            return new Control_Monad_Rec_Class.Loop({
                                seed: v1.value1.newSeed,
                                index: v.index + 1 | 0,
                                successes: v.successes,
                                firstFailure: Data_Semigroup.append(Data_Maybe_First.semigroupFirst)(v.firstFailure)(new Data_Maybe.Just({
                                    index: v.index,
                                    message: v1.value0.value0,
                                    seed: v.seed
                                }))
                            });
                        };
                        throw new Error("Failed pattern match at Test.QuickCheck (line 112, column 9 - line 127, column 16): " + [ v1.constructor.name ]);
                    };
                    throw new Error("Failed pattern match at Test.QuickCheck (line 108, column 3 - line 108, column 48): " + [ v.constructor.name ]);
                };
                var result = Control_Monad_Rec_Class.tailRec(loop)({
                    seed: initialSeed,
                    index: 0,
                    successes: 0,
                    firstFailure: Data_Monoid.mempty(Data_Maybe_First.monoidFirst)
                });
                return function __do() {
                    Effect_Console.log(Data_Show.show(Data_Show.showInt)(result.successes) + ("/" + (Data_Show.show(Data_Show.showInt)(n) + " test(s) passed.")))();
                    return Data_Foldable.for_(Effect.applicativeEffect)(Data_Foldable.foldableFirst)(result.firstFailure)(function (v) {
                        return Effect_Exception.throwException(Effect_Exception.error("Test " + (Data_Show.show(Data_Show.showInt)(v.index + 1 | 0) + (" (seed " + (Data_Show.show(Data_Show.showInt)(Random_LCG.unSeed(v.seed)) + (") failed: \x0a" + v.message))))));
                    })();
                };
            };
        };
    };
};
var quickCheckPure = function (dictTestable) {
    return function (s) {
        return function (n) {
            return function (prop) {
                return Test_QuickCheck_Gen.evalGen(Data_Unfoldable.replicateA(Test_QuickCheck_Gen.applicativeGen)(Data_List_Types.unfoldableList)(Data_List_Types.traversableList)(n)(test(dictTestable)(prop)))({
                    newSeed: s,
                    size: 10
                });
            };
        };
    };
};
var quickCheckGenWithSeed = function (dictTestable) {
    return quickCheckWithSeed(testableGen(dictTestable));
};
var quickCheckGenPure = function (dictTestable) {
    return quickCheckPure(testableGen(dictTestable));
};
var quickCheck$prime = function (dictTestable) {
    return function (n) {
        return function (prop) {
            return function __do() {
                var v = Random_LCG.randomSeed();
                return quickCheckWithSeed(dictTestable)(v)(n)(prop)();
            };
        };
    };
};
var quickCheckGen$prime = function (dictTestable) {
    return quickCheck$prime(testableGen(dictTestable));
};
var quickCheck = function (dictTestable) {
    return function (prop) {
        return quickCheck$prime(dictTestable)(100)(prop);
    };
};
var quickCheckGen = function (dictTestable) {
    return quickCheck(testableGen(dictTestable));
};
var assertOp = function (dictEq) {
    return function (dictShow) {
        return function (op) {
            return function (failString) {
                return function (a) {
                    return function (b) {
                        return withHelp(op(a)(b))(Data_Show.show(dictShow)(a) + (failString + Data_Show.show(dictShow)(b)));
                    };
                };
            };
        };
    };
};
var assertNotEquals = function (dictEq) {
    return function (dictShow) {
        return assertOp(dictEq)(dictShow)(Data_Eq.notEq(dictEq))(" == ");
    };
};
var assertLessThanEq = function (dictOrd) {
    return function (dictShow) {
        return assertOp(dictOrd.Eq0())(dictShow)(Data_Ord.lessThanOrEq(dictOrd))(" > ");
    };
};
var assertLessThan = function (dictOrd) {
    return function (dictShow) {
        return assertOp(dictOrd.Eq0())(dictShow)(Data_Ord.lessThan(dictOrd))(" >= ");
    };
};
var assertGreaterThanEq = function (dictOrd) {
    return function (dictShow) {
        return assertOp(dictOrd.Eq0())(dictShow)(Data_Ord.greaterThanOrEq(dictOrd))(" < ");
    };
};
var assertGreaterThan = function (dictOrd) {
    return function (dictShow) {
        return assertOp(dictOrd.Eq0())(dictShow)(Data_Ord.greaterThan(dictOrd))(" <= ");
    };
};
var assertEquals = function (dictEq) {
    return function (dictShow) {
        return assertOp(dictEq)(dictShow)(Data_Eq.eq(dictEq))(" /= ");
    };
};
module.exports = {
    quickCheck: quickCheck,
    quickCheckGen: quickCheckGen,
    "quickCheck'": quickCheck$prime,
    "quickCheckGen'": quickCheckGen$prime,
    quickCheckWithSeed: quickCheckWithSeed,
    quickCheckGenWithSeed: quickCheckGenWithSeed,
    quickCheckPure: quickCheckPure,
    quickCheckGenPure: quickCheckGenPure,
    Testable: Testable,
    test: test,
    Success: Success,
    Failed: Failed,
    withHelp: withHelp,
    assertEquals: assertEquals,
    assertNotEquals: assertNotEquals,
    assertLessThan: assertLessThan,
    assertLessThanEq: assertLessThanEq,
    assertGreaterThan: assertGreaterThan,
    assertGreaterThanEq: assertGreaterThanEq,
    testableResult: testableResult,
    testableBoolean: testableBoolean,
    testableFunction: testableFunction,
    testableGen: testableGen,
    showResult: showResult
};
