"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OracleRule = void 0;
exports.Oracle = Oracle;
const tslib_1 = require("tslib");
const fast_deep_equal_1 = tslib_1.__importDefault(require("fast-deep-equal"));
const interface_1 = require("../core/interface");
const rule_base_1 = require("./rule-base");
const util_1 = require("./util");
class OracleRule extends rule_base_1.RuleBase {
    constructor(isOracle, matcher, FRecipe) {
        super(matcher);
        this.isOracle = isOracle;
        this.FRecipe = FRecipe;
        this.kindTag = "Mock::OracleRule";
    }
    matchString(id) {
        return null;
    }
    async build(t, ...args) {
        const result = await this.FRecipe(t, ...args);
        if (t.lastResult !== undefined && result !== undefined && (0, fast_deep_equal_1.default)(t.lastResult, result)) {
            t.is.not.modified();
        }
        else {
            t.is.modified();
        }
        return result;
    }
    async preBuild(t) {
        if (this.isOracle || t.isVolatile) {
            await t.dependencyModified();
            return (await t.cutoffEarly()) ? interface_1.PreBuildResult.YES : interface_1.PreBuildResult.NO;
        }
        else {
            if (!(await t.dependencyModified()))
                return interface_1.PreBuildResult.NO;
            return (await t.cutoffEarly()) ? interface_1.PreBuildResult.YES : interface_1.PreBuildResult.NO;
        }
    }
    async shouldTriggerModify(t, itselfModified) {
        return itselfModified;
    }
}
exports.OracleRule = OracleRule;
function Oracle(dir) {
    const _oracle = (0, util_1.SinglePlural_T)("Builtin::Oracle::", dir, (matcher, FRecipe) => new OracleRule(true, matcher, FRecipe));
    const _computed = (0, util_1.SinglePlural_T)("Builtin::Computed::", dir, (matcher, FRecipe) => new OracleRule(false, matcher, FRecipe));
    return {
        oracle: Object.assign(_oracle.exact, {
            glob: _oracle.glob,
            group: _oracle.subPrefix,
            make: _oracle.make,
        }),
        computed: Object.assign(_computed.exact, {
            glob: _computed.glob,
            group: _computed.subPrefix,
            make: _computed.make,
        }),
    };
}
