/// <reference types="node" />
import { MaybePromise, Undefinable } from '@thermopylae/core.declarations';
import { EventEmitter } from 'events';
import { Cache, CacheEvent, CacheEventListener } from '../contracts/cache';
import { CacheReplacementPolicy } from '../contracts/cache-replacement-policy';
import { CacheBackend } from '../contracts/cache-backend';
import { CacheEntry } from '../contracts/commons';
/**
 * @private
 */
declare const POLICIES_SYM: unique symbol;
/**
 * @private
 */
interface CacheEntryEvictedBySpecialisedPolicies<Key, Value, PolicyTag> extends CacheEntry<Key, Value> {
    [POLICIES_SYM]: ReadonlyArray<PolicyTag>;
}
interface PolicyPerKeyCacheArgumentsBundle<PolicyTag> {
    /**
     * Array of policies used for a particular key. <br/>
     * If not given, key will be tracked by all of the available policies.
     */
    policies?: ReadonlyArray<PolicyTag>;
}
/**
 * {@link Cache} implementation which uses {@link CacheReplacementPolicy} for keys eviction. <br/>
 * It can selectively use different policies for a particular key.
 * In order to do so, each policy is tagged for further identification.
 * When client inserts a new key, it can specify a list of policy tags which will track that key.
 * If it doesn't specify any tags, key will be tracked by all of the available policies. <br/>
 * Although any predefined policy can be used, there are some restrictions for multiple policies combination. <br/>
 * You can combine only 1 policy from each category in the {@link PolicyPerKeyCacheArgumentsBundle.policies}.
 * Also be careful, as when you omit {@link PolicyPerKeyCacheArgumentsBundle.policies}, cache will enforce all of the
 * registered policies for that key, therefore if you have registered multiple policies from same category,
 * this will result in **undefined behaviour**.
 *
 * Category			|	Policies
 * ---------------- | -----------------------------
 * Expiration		| - {@link ProactiveExpirationPolicy}<br/>- {@link ReactiveExpirationPolicy}<br/>- {@link SlidingProactiveExpirationPolicy}<br/>- {@link SlidingReactiveExpirationPolicy}
 * Eviction			| - {@link ArcEvictionPolicy}<br/>- {@link LRUEvictionPolicy}<br/>- {@link SegmentedLRUEvictionPolicy}<br/>- {@link LFUEvictionPolicy}<br/>- {@link LFUDAEvictionPolicy}<br/>- {@link GDSFEvictionPolicy}
 * Priority			| - {@link PriorityEvictionPolicy}
 * Dependencies		| - {@link KeysDependenciesEvictionPolicy}
 *
 * For example, the following combination is a valid one: [{@link ProactiveExpirationPolicy}, {@link LRUEvictionPolicy}, {@link KeysDependenciesEvictionPolicy}].<br/>
 * While the following: [{@link ProactiveExpirationPolicy}, {@link SlidingProactiveExpirationPolicy}] isn't, because it contains 2 policies from same category.
 *
 * @template Key				Type of the key.
 * @template Value				Type of the value.
 * @template PolicyTag			Type of the policy tag.
 * @template ArgumentsBundle	Type of the arguments bundle.
 */
declare class PolicyPerKeyCache<Key, Value, PolicyTag = string, ArgumentsBundle extends PolicyPerKeyCacheArgumentsBundle<PolicyTag> = PolicyPerKeyCacheArgumentsBundle<PolicyTag>> extends EventEmitter implements Cache<Key, Value, ArgumentsBundle> {
    /**
     * @private
     */
    private readonly backend;
    private readonly policies;
    private readonly allPoliciesTags;
    /**
     * @param backend		Cache backend.
     * @param policies		Tagged cache replacement policies.
     */
    constructor(backend: CacheBackend<Key, Value>, policies: ReadonlyMap<PolicyTag, CacheReplacementPolicy<Key, Value, ArgumentsBundle>>);
    /**
     * @inheritDoc
     */
    get size(): number;
    /**
     * @inheritDoc
     */
    get(key: Key): Undefinable<Value>;
    /**
     * @inheritDoc
     */
    set(key: Key, value: Value, argsBundle?: ArgumentsBundle): void;
    /**
     * Check whether **key** is present in the cache, without calling policies *onHit* hook. <br/>
     * Notice, that some policies might evict item when *onHit* hook is called (e.g. item expired),
     * therefore even if method returns **true**, trying to *get* item might evict him.
     *
     * @param key	Name of the key.
     */
    has(key: Key): boolean;
    /**
     * @inheritDoc
     */
    del(key: Key): boolean;
    /**
     * @inheritDoc
     */
    clear(): void;
    /**
     * @inheritDoc
     */
    keys(): Array<Key>;
    /**
     * @inheritDoc
     */
    on(event: CacheEvent, listener: CacheEventListener<Key, MaybePromise<Value, 'plain'>>): this;
    private internalDelete;
}
export { PolicyPerKeyCache, PolicyPerKeyCacheArgumentsBundle, CacheEntryEvictedBySpecialisedPolicies };
