"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntityDefinitionCache = void 0;
const guard_1 = __importDefault(require("../guard"));
/**
 * Caches definition in memory.
 */
class EntityDefinitionCache {
    constructor() {
        this._allCacheKey = "__ALL__";
        this._promiseKeyPrefix = "PROMISE__";
        this._map = new Map();
        this._map = new Map();
    }
    /**
     * Load the specified definition into the cache.
     * @param definition - The entity definition
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definition
     */
    load(definition, includeConditionalMembers, loadPermissions) {
        guard_1.default.notNullOrUndefined(definition, "definition");
        guard_1.default.notNullOrUndefined(definition.id, "definition id");
        this._map.set(this.getCacheKey(definition.name, { includeConditionalMembers, loadPermissions }), definition);
        this._map.set(this.getCacheKey(definition.id.toString(), { includeConditionalMembers, loadPermissions }), definition);
    }
    /**
     * Load the specified definition into the cache asynchronously.
     * @param key - The definition name or definition id
     * @param promise - A promise resolving to the definition
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definition
     */
    loadAsync(key, promise, includeConditionalMembers, loadPermissions) {
        this.validateKey(key);
        guard_1.default.notNullOrUndefined(promise);
        this._map.set(`${this._promiseKeyPrefix}${this.getCacheKey(key.toString(), {
            includeConditionalMembers,
            loadPermissions,
        })}`, promise);
        const loadPromise = promise.then(definition => {
            if (definition) {
                this.load(definition);
            }
        });
        return loadPromise;
    }
    /**
     * Retrieve the definition with specified name or id from the cache.
     * @param key - The definition name or definition id
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definition
     * @returns The cached definition or null
     */
    get(key, includeConditionalMembers, loadPermissions) {
        this.validateKey(key);
        const res = this._map.get(this.getCacheKey(key.toString(), { includeConditionalMembers, loadPermissions })) || null;
        return res;
    }
    /**
     * Retrieve the definition with specified name or id from the cache asynchronously.
     * @param key - The definition name or definition id
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definition
     * @returns A promise resolving to the cached definition or null
     */
    getAsync(key, includeConditionalMembers, loadPermissions) {
        this.validateKey(key);
        const promise = (this._map.get(`${this._promiseKeyPrefix}${this.getCacheKey(key.toString(), {
            includeConditionalMembers,
            loadPermissions,
        })}`) || null);
        if (promise != null) {
            return promise;
        }
        const definition = (this.get(this.getCacheKey(key.toString(), { includeConditionalMembers, loadPermissions })) || null);
        if (definition != null) {
            return Promise.resolve(definition);
        }
        return null;
    }
    /**
     * Loads all definitions into the cache.
     * @param definitions - An array of entity definitions
     * @param loadAllIndividually - Flag indicating whether to load the definitions individually or not
     * @param loadAsGroup - Key to be used to store the array of definitions, or false to not load the array
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definitions
     */
    loadAll(definitions, loadAllIndividually = true, loadAsGroup = this._allCacheKey, includeConditionalMembers, loadPermissions, viewMode, excludeTaxonomyDefinitions, excludeSystemOwnedDefinitions, filter, definitionsToLoadByName, definitionsToLoadById) {
        guard_1.default.notNullOrUndefined(definitions);
        if (definitions.length === 0) {
            return;
        }
        if (loadAsGroup) {
            guard_1.default.stringNotNullOrEmpty(loadAsGroup);
            this._map.set(this.getCacheKey(loadAsGroup, {
                filter,
                definitionsToLoadByName,
                definitionsToLoadById,
                viewMode,
                loadPermissions,
                includeConditionalMembers,
                excludeTaxonomyDefinitions,
                excludeSystemOwnedDefinitions,
            }), definitions);
        }
        if (loadAllIndividually) {
            definitions.forEach(definition => this.load(definition, includeConditionalMembers, loadPermissions), this);
        }
    }
    /**
     * Retrieves an array of definitions that was cached with the specified group key.
     *
     * @remarks
     * Can not be used to retrieve a single cached definition. Use {@link EntityDefinitionCache.get} instead.
     *
     * @param group - The key with which the group of definitions was stored
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definitions
     */
    getAll(group = this._allCacheKey, includeConditionalMembers, loadPermissions, viewMode, excludeTaxonomyDefinitions, excludeSystemOwnedDefinitions, filter, definitionsToLoadByName, definitionsToLoadById) {
        const res = this._map.get(this.getCacheKey(group, {
            filter,
            definitionsToLoadByName,
            definitionsToLoadById,
            viewMode,
            loadPermissions,
            includeConditionalMembers,
            excludeTaxonomyDefinitions,
            excludeSystemOwnedDefinitions,
        })) || null;
        return res instanceof Array ? res : null;
    }
    /**
     * Invalidates/removes the definition with specified name or id from the cache.
     * @param key - The definition name or definition id
     * @param includeConditionalMembers - Include conditional members
     * @param loadPermissions - Load permissions for the definition
     */
    invalidate(key, includeConditionalMembers, loadPermissions) {
        if (!key) {
            this._map.clear();
            return;
        }
        this.validateKey(key);
        const definition = this.get(key);
        if (!definition)
            return;
        this._map.delete(this.getCacheKey(definition.name, { includeConditionalMembers, loadPermissions }));
        this._map.delete(this.getCacheKey(definition.id.toString(), { includeConditionalMembers, loadPermissions }));
    }
    validateKey(key) {
        if (typeof key === "string") {
            guard_1.default.stringNotNullOrEmpty(key);
        }
        else {
            guard_1.default.validId(key);
        }
    }
    getCacheKey(key, { filter, definitionsToLoadByName, definitionsToLoadById, viewMode, loadPermissions, includeConditionalMembers, excludeTaxonomyDefinitions, excludeSystemOwnedDefinitions, }) {
        return [
            key.trim().toLowerCase(),
            includeConditionalMembers && "conditionals",
            loadPermissions && "permissions",
            viewMode,
            excludeTaxonomyDefinitions && "excludeTaxonomyDefinitions",
            excludeSystemOwnedDefinitions && "excludeSystemOwnedDefinitions",
            filter,
            definitionsToLoadByName,
            definitionsToLoadById,
        ]
            .filter(Boolean)
            .join("-");
    }
}
exports.EntityDefinitionCache = EntityDefinitionCache;
//# sourceMappingURL=entity-definition-cache.js.map