"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SimpleLruCache = void 0;
class SimpleLruCache {
    constructor() {
        this.nodesMap = new Map();
        this.firstNode = null;
        this.lastNode = null;
    }
    get size() {
        return this.nodesMap.size;
    }
    /**
     * Get a value if is cached. Note: null values are indistinguishable from absent value
     */
    getCached(key) {
        const retrieved = this.nodesMap.get(key);
        if (retrieved !== undefined) {
            this.markUsed(retrieved);
            return retrieved.value;
        }
        else {
            return null;
        }
    }
    set(key, value) {
        const retrieved = this.nodesMap.get(key);
        if (retrieved !== undefined) {
            this.markUsed(retrieved);
            retrieved.value = value;
        }
        else {
            const newNode = {
                key: key,
                value: value,
                previous: null,
                next: null,
            };
            this.addToTail(key, newNode);
        }
    }
    /**
     * Fully empties this cache.
     */
    clear() {
        this.firstNode = null;
        this.lastNode = null;
        this.nodesMap.clear();
    }
    evictLeastRecentlyUsed() {
        const node = this.firstNode;
        if (node == null)
            throw new Error('Internal error: no node left to evict');
        this.evict(node.key, node);
        return node.value;
    }
    addToTail(updateKey, node) {
        node.previous = this.lastNode;
        node.next = null;
        if (this.lastNode)
            this.lastNode.next = node;
        this.lastNode = node;
        if (this.firstNode === null)
            this.firstNode = node;
        if (updateKey != null)
            this.nodesMap.set(updateKey, node);
    }
    evict(updateKey, node) {
        if (node.previous)
            node.previous.next = node.next;
        if (node.next)
            node.next.previous = node.previous;
        if (this.firstNode === node)
            this.firstNode = node.next;
        if (this.lastNode === node)
            this.lastNode = node.previous;
        if (updateKey !== null) {
            this.nodesMap.delete(updateKey);
        }
    }
    markUsed(node) {
        if (node !== this.lastNode) {
            // No need to modify the nodes map
            this.evict(null, node);
            this.addToTail(null, node);
        }
    }
}
exports.SimpleLruCache = SimpleLruCache;
//# sourceMappingURL=simple-lru-cache.js.map