"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sieve = void 0;
const types_1 = require("../types");
const logger_1 = require("../utils/logger");
const helpers_1 = require("../utils/helpers");
const DEFAULT_ORDERS_TTL_MS = 60 * 10 * 1000 * 2; // 20 minutes
class Sieve {
    static singleton = null;
    items = new Map();
    orders = new Map();
    attestations = new Map();
    ORDERS_TTL_MS;
    constructor(_ORDERS_TTL_MS) {
        this.ORDERS_TTL_MS = _ORDERS_TTL_MS;
        this.orders = new Map();
    }
    static getInstance(_ORDERS_TTL_MS) {
        if (this.singleton === null) {
            const ordersTTL = _ORDERS_TTL_MS || DEFAULT_ORDERS_TTL_MS;
            this.singleton = new Sieve(ordersTTL);
        }
        return this.singleton;
    }
    async start() {
        logger_1.logger.info(`🧺 Starting Sieve with orders TTL: ${this.ORDERS_TTL_MS / 1000}s `);
        while (true) {
            await this.clearOrders();
        }
    }
    addItem(id, event, txHash) {
        if (!this.items.has(id)) {
            this.items.set(id, {
                id,
                event,
                val: txHash,
                createdTimestamp: Date.now(),
            });
            return true;
        }
        return false;
    }
    hasItem(id) {
        return this.items.has(id);
    }
    addOrder(order) {
        if (!this.orders.has(order.id)) {
            this.orders.set(order.id, {
                order,
                event: types_1.EventName.OrderCreated,
                sift: {},
                createdTimestamp: Date.now(),
            });
            return true;
        }
        return false;
    }
    addAttestation(orderId, attestation) {
        if (!this.attestations.has(orderId)) {
            this.attestations.set(orderId, {
                attestation: attestation,
                createdTimestamp: Date.now(),
                isFirstTime: true,
            });
        }
    }
    getAttestation(orderId) {
        const result = { attestation: null, isFirstTime: true, createdTimestamp: 0 };
        const sieveAttestation = this.attestations.get(orderId);
        if (sieveAttestation) {
            if (sieveAttestation.isFirstTime) {
                sieveAttestation.isFirstTime = false;
                // Update the attestation is first time to false
                this.attestations.set(orderId, sieveAttestation);
                return sieveAttestation;
            }
            return sieveAttestation;
        }
        return result;
    }
    siftId(orderId, event) {
        const result = { order: undefined, isFirstTime: true };
        const sieveOrderObj = this.orders.get(orderId);
        if (!sieveOrderObj) {
            return result;
        }
        result.order = sieveOrderObj.order;
        if (!sieveOrderObj.sift[event]) {
            sieveOrderObj.sift[event] = true;
        }
        else {
            result.isFirstTime = false;
        }
        return result;
    }
    async clearOrders() {
        await (0, helpers_1.sleep)(60, 'Waiting between cleaning Sieve orders');
        const now = Date.now();
        // Clear orders that are older than the TTL
        for (const [id, item] of this.items.entries()) {
            if (now - item.createdTimestamp > this.ORDERS_TTL_MS) {
                this.items.delete(id);
            }
        }
        for (const [id, order] of this.orders.entries()) {
            if (now - order.createdTimestamp > this.ORDERS_TTL_MS) {
                this.orders.delete(id);
            }
        }
        for (const [id, order] of this.attestations.entries()) {
            if (now - order.createdTimestamp > this.ORDERS_TTL_MS) {
                this.attestations.delete(id);
            }
        }
    }
}
exports.Sieve = Sieve;
//# sourceMappingURL=sieve.js.map