"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DerivationContext = exports.mergeEnvironments = exports.overridable = exports.replaceServiceIn_ = exports.replaceServiceIn = exports.tag = void 0;
// ets_tracing: off
require("../Operator");
const Option_1 = require("../Option");
const makeTag = (def = false, key = Symbol()) => ({
    _tag: "Tag",
    _T: undefined,
    key,
    def,
    of: (t) => ({ [key]: t }),
    overridable: () => makeTag(true, key),
    fixed: () => makeTag(false, key),
    refine: () => makeTag(def, key),
    read: (r) => r[key],
    readOption: (r) => typeof r === "object" && r !== null ? (0, Option_1.fromNullable)(r[key]) : Option_1.none,
    setKey: (s) => makeTag(def, s)
});
function tag(_) {
    return makeTag();
}
exports.tag = tag;
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */
const replaceServiceIn = (_, f) => (r) => ({
    ...r,
    [_.key]: f(r[_.key])
});
exports.replaceServiceIn = replaceServiceIn;
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */
const replaceServiceIn_ = (r, _, f) => ({
    ...r,
    [_.key]: f(r[_.key])
});
exports.replaceServiceIn_ = replaceServiceIn_;
/**
 * Flags the current Has to be overridable, when this is used subsequently provided
 * environments will override pre-existing. Useful to provide defaults.
 */
const overridable = (h) => ({
    ...h,
    def: true
});
exports.overridable = overridable;
function mergeEnvironments(_, r, t) {
    return _.def && r[_.key]
        ? r
        : {
            ...r,
            [_.key]: t
        };
}
exports.mergeEnvironments = mergeEnvironments;
class DerivationContext {
    constructor() {
        this.hasMap = new Map();
    }
    derive(has, f) {
        const inMap = this.hasMap.get(has);
        if (inMap) {
            return inMap;
        }
        const computed = f();
        this.hasMap.set(has, computed);
        return computed;
    }
}
exports.DerivationContext = DerivationContext;
//# sourceMappingURL=index.js.map