type PK = string | number;

interface IEvictionManager<K extends PK> {
    recordAccess(key: PK): void;
    selectEvictionKey(): PK | undefined;
    removeKey(key: PK): void;
}

declare abstract class CacheDataStorageManager<K extends PK, V> {
    protected capacity: number;
    protected evictionManager: IEvictionManager<K>;
    constructor(capacity: number, evictionManager: IEvictionManager<K>);
    getCapacity(): number;
    getEvictionManager(): IEvictionManager<K>;
    abstract add(key: K, value: V): void;
    abstract get(key: K): V | undefined;
    abstract has(key: K): boolean;
    abstract delete(key: K): boolean;
    abstract clear(): void;
    abstract listAll(): Array<{
        key: K;
        value: V;
    }>;
}

declare enum StorageType {
    InMemoryStorage = 0,
    NotImplementedStorage = 1
}

declare class CacheDataStorageFactory {
    create<K extends PK, V>(capacity: number, storageType: StorageType, evictionManager: IEvictionManager<K>): CacheDataStorageManager<K, V>;
}

declare enum ReplacementPolicy {
    LRU = 0,
    MRU = 1
}

declare class EvictionManagerFactory {
    create<K extends PK>(policy: ReplacementPolicy): any;
}

interface INWaySetAssociativeCache<K extends PK, V> {
    put(key: K, value: V): void;
    get(key: K): V | undefined;
    has(key: K): boolean;
    delete(key: K): boolean;
    clear(): void;
    listAll(): Array<{
        key: K;
        value: V;
    }>;
}

interface Logger {
    info: (message: string, ...args: any[]) => void;
    warn: (message: string, ...args: any[]) => void;
    error: (message: string, ...args: any[]) => void;
}

declare class NWaySetAssociativeCache<K extends PK, V> implements INWaySetAssociativeCache<K, V> {
    private cache;
    private capacity;
    private ways;
    private policy;
    private storageType;
    private storageFactory;
    private evictionManagerFactory;
    private logger;
    constructor(capacity: number, ways: number, policy?: ReplacementPolicy, storageType?: StorageType, storageFactory?: CacheDataStorageFactory, evictionManagerFactory?: EvictionManagerFactory, logger?: Logger);
    private getSetIndex;
    private hashKey;
    put(key: K, value: V): void;
    get(key: K): V | undefined;
    has(key: K): boolean;
    delete(key: K): boolean;
    clear(): void;
    listAll(): {
        key: K;
        value: V;
    }[];
}

export { NWaySetAssociativeCache };
