import { resourceManager } from '../utilities/resource-manager.js';
const DEFAULT_REGISTRY_CONFIG = {
    maxComponents: 1000,
    cleanupInterval: 60000,
    useLRU: true,
    enableNamespaces: true
};
export class ComponentRegistry {
    constructor(config) {
        this.config = { ...DEFAULT_REGISTRY_CONFIG, ...config };
        this.registry = new Map();
        this.registryId = `component-registry-${Date.now()}`;
        if (this.config.cleanupInterval > 0) {
            this.startCleanupTimer();
        }
    }
    register(name, component, namespace = 'Global', version = 'v1', contentHash, tags) {
        const id = this.generateRegistryKey(name, namespace, version, contentHash);
        const metadata = {
            id,
            name,
            version,
            namespace,
            registeredAt: new Date(),
            tags
        };
        const entry = {
            component,
            metadata,
            lastAccessed: new Date(),
            refCount: 0
        };
        if (this.registry.size >= this.config.maxComponents && this.config.useLRU) {
            this.evictLRU();
        }
        this.registry.set(id, entry);
        return metadata;
    }
    get(name, namespace = 'Global', version, contentHash) {
        const id = this.resolveLookupKey(name, namespace, version, contentHash);
        if (!id)
            return undefined;
        const entry = this.registry.get(id);
        if (entry) {
            entry.lastAccessed = new Date();
            entry.refCount++;
            return entry.component;
        }
        return undefined;
    }
    has(name, namespace = 'Global', version, contentHash) {
        const id = this.resolveLookupKey(name, namespace, version, contentHash);
        return id ? this.registry.has(id) : false;
    }
    unregister(name, namespace = 'Global', version, contentHash) {
        const id = this.resolveLookupKey(name, namespace, version, contentHash);
        if (!id)
            return false;
        return this.registry.delete(id);
    }
    getNamespace(namespace) {
        const components = [];
        for (const entry of this.registry.values()) {
            if (entry.metadata.namespace === namespace) {
                components.push(entry.metadata);
            }
        }
        return components;
    }
    getAll(namespace = 'Global', version = 'v1') {
        const components = {};
        for (const entry of this.registry.values()) {
            if (entry.metadata.namespace === namespace && entry.metadata.version === version) {
                components[entry.metadata.name] = entry.component;
            }
        }
        return components;
    }
    getNamespaces() {
        const namespaces = new Set();
        for (const entry of this.registry.values()) {
            namespaces.add(entry.metadata.namespace);
        }
        return Array.from(namespaces);
    }
    getByTags(tags) {
        const components = [];
        for (const entry of this.registry.values()) {
            if (entry.metadata.tags?.some(tag => tags.includes(tag))) {
                components.push(entry.metadata);
            }
        }
        return components;
    }
    release(name, namespace = 'Global', version, contentHash) {
        const id = this.resolveLookupKey(name, namespace, version, contentHash);
        if (!id)
            return;
        const entry = this.registry.get(id);
        if (entry && entry.refCount > 0) {
            entry.refCount--;
        }
    }
    clear() {
        this.registry.clear();
    }
    clearNamespace(namespace = 'Global') {
        const toRemove = [];
        for (const [key, entry] of this.registry) {
            if (entry.metadata.namespace === namespace) {
                toRemove.push(key);
            }
        }
        for (const key of toRemove) {
            this.registry.delete(key);
        }
        return toRemove.length;
    }
    forceClear() {
        this.stopCleanupTimer();
        this.registry.clear();
        console.log('🧹 Registry force cleared - all components removed');
    }
    size() {
        return this.registry.size;
    }
    cleanup(force = false) {
        const toRemove = [];
        const now = Date.now();
        for (const [id, entry] of this.registry) {
            const timeSinceAccess = now - entry.lastAccessed.getTime();
            const isUnused = entry.refCount === 0 && timeSinceAccess > this.config.cleanupInterval;
            if (force || isUnused) {
                toRemove.push(id);
            }
        }
        for (const id of toRemove) {
            this.registry.delete(id);
        }
        return toRemove.length;
    }
    getStats() {
        let totalRefCount = 0;
        let oldest;
        let newest;
        for (const entry of this.registry.values()) {
            totalRefCount += entry.refCount;
            if (!oldest || entry.metadata.registeredAt < oldest) {
                oldest = entry.metadata.registeredAt;
            }
            if (!newest || entry.metadata.registeredAt > newest) {
                newest = entry.metadata.registeredAt;
            }
        }
        return {
            totalComponents: this.registry.size,
            namespaces: this.getNamespaces().length,
            totalRefCount,
            oldestComponent: oldest,
            newestComponent: newest
        };
    }
    destroy() {
        this.stopCleanupTimer();
        this.clear();
        resourceManager.cleanupComponent(this.registryId);
    }
    generateRegistryKey(name, namespace, version, contentHash) {
        const base = this.config.enableNamespaces ? `${namespace}::${name}@${version}` : `${name}@${version}`;
        return contentHash ? `${base}#${contentHash}` : base;
    }
    resolveLookupKey(name, namespace, version, contentHash) {
        if (version && contentHash) {
            return this.generateRegistryKey(name, namespace, version, contentHash);
        }
        if (version) {
            return this.findLatestForVersion(name, namespace, version);
        }
        return this.findLatestVersion(name, namespace);
    }
    findLatestForVersion(name, namespace, version) {
        let latestKey;
        let latestDate;
        for (const [key, entry] of this.registry) {
            if (entry.metadata.name === name &&
                entry.metadata.namespace === namespace &&
                entry.metadata.version === version) {
                if (!latestDate || entry.metadata.registeredAt > latestDate) {
                    latestDate = entry.metadata.registeredAt;
                    latestKey = key;
                }
            }
        }
        return latestKey;
    }
    findLatestVersion(name, namespace) {
        let latestKey;
        let latestDate;
        for (const [key, entry] of this.registry) {
            if (entry.metadata.name === name &&
                entry.metadata.namespace === namespace) {
                if (!latestDate || entry.metadata.registeredAt > latestDate) {
                    latestDate = entry.metadata.registeredAt;
                    latestKey = key;
                }
            }
        }
        return latestKey;
    }
    evictLRU() {
        let lruKey;
        let lruTime;
        for (const [key, entry] of this.registry) {
            if (entry.refCount > 0)
                continue;
            if (!lruTime || entry.lastAccessed < lruTime) {
                lruTime = entry.lastAccessed;
                lruKey = key;
            }
        }
        if (lruKey) {
            this.registry.delete(lruKey);
        }
    }
    startCleanupTimer() {
        this.cleanupTimer = resourceManager.setInterval(this.registryId, () => {
            this.cleanup();
        }, this.config.cleanupInterval, { purpose: 'component-registry-cleanup' });
    }
    stopCleanupTimer() {
        if (this.cleanupTimer) {
            resourceManager.clearInterval(this.registryId, this.cleanupTimer);
            this.cleanupTimer = undefined;
        }
    }
}
//# sourceMappingURL=component-registry.js.map