"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.option = void 0;
const Arbitrary_1 = require("./definition/Arbitrary");
const Shrinkable_1 = require("./definition/Shrinkable");
const IntegerArbitrary_1 = require("./IntegerArbitrary");
class OptionArbitrary extends Arbitrary_1.Arbitrary {
    constructor(arb, frequency, nil) {
        super();
        this.arb = arb;
        this.frequency = frequency;
        this.nil = nil;
        this.isOptionArb = IntegerArbitrary_1.nat(frequency);
    }
    static extendedShrinkable(s, nil) {
        function* g() {
            yield new Shrinkable_1.Shrinkable(nil);
        }
        return new Shrinkable_1.Shrinkable(s.value_, () => s
            .shrink()
            .map((v) => OptionArbitrary.extendedShrinkable(v, nil))
            .join(g()));
    }
    generate(mrng) {
        return this.isOptionArb.generate(mrng).value === 0
            ? new Shrinkable_1.Shrinkable(this.nil)
            : OptionArbitrary.extendedShrinkable(this.arb.generate(mrng), this.nil);
    }
    withBias(freq) {
        return new OptionArbitrary(this.arb.withBias(freq), this.frequency, this.nil);
    }
}
function option(arb, constraints) {
    if (!constraints)
        return new OptionArbitrary(arb, 5, null);
    if (typeof constraints === 'number')
        return new OptionArbitrary(arb, constraints, null);
    return new OptionArbitrary(arb, constraints.freq == null ? 5 : constraints.freq, Object.prototype.hasOwnProperty.call(constraints, 'nil') ? constraints.nil : null);
}
exports.option = option;
