"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpiringSortedSet = void 0;
const __1 = require("..");
const logger = (0, __1.makeLogger)('ExpiringSortedSet');
/**
 * This class implements a set of unique items, each of which has an expiration timestamp.
 * On reads, items that have expired will be deleted from the set and not returned.
 *
 * @typeParam T - the type of the set entries' values
 */
class ExpiringSortedSet {
    constructor(capacity) {
        this.capacity = capacity;
        this.map = new Map();
        this.list = new __1.DoubleLinkedList();
    }
    add(value, ttl, key) {
        let node = this.map.get(key);
        if (node) {
            node.data = {
                value,
                expirationTimestamp: Date.now() + ttl,
            };
            this.moveToTail(node);
        }
        else {
            this.evictIfNeeded();
            const data = {
                value,
                expirationTimestamp: Date.now() + ttl,
            };
            node = new __1.LinkedListNode(key, data);
            this.list.insertAtTail(node);
            this.map.set(key, node);
        }
    }
    getAll() {
        const results = [];
        for (const [key] of this.map.entries()) {
            const value = this.get(key);
            if (value) {
                results.push(value);
            }
        }
        return results;
    }
    get(key) {
        const node = this.map.get(key);
        if (node) {
            const expired = node.data.expirationTimestamp <= Date.now();
            if (expired) {
                this.delete(key);
                return undefined;
            }
            else {
                return node.data.value;
            }
        }
        else {
            return undefined;
        }
    }
    delete(key) {
        const node = this.map.get(key);
        if (node) {
            this.list.remove(node);
            this.map.delete(key);
        }
    }
    moveToTail(node) {
        this.list.remove(node);
        this.list.insertAtTail(node);
    }
    evictIfNeeded() {
        if (this.list.size >= this.capacity) {
            const node = this.list.removeHead();
            if (node) {
                logger.warn(`List reached maximum capacity, evicting least recently updated entry. The subscription with key ${node.key} was removed.`);
                this.map.delete(node.key);
            }
        }
    }
}
exports.ExpiringSortedSet = ExpiringSortedSet;
//# sourceMappingURL=expiring-sorted-set.js.map