const getTimerFunctions = () => {
    if (typeof window !== 'undefined' && window.setTimeout) {
        return {
            setTimeout: window.setTimeout.bind(window),
            clearTimeout: window.clearTimeout.bind(window),
            setInterval: window.setInterval.bind(window),
            clearInterval: window.clearInterval.bind(window),
            requestAnimationFrame: window.requestAnimationFrame?.bind(window),
            cancelAnimationFrame: window.cancelAnimationFrame?.bind(window)
        };
    }
    else if (typeof global !== 'undefined' && global.setTimeout) {
        return {
            setTimeout: global.setTimeout,
            clearTimeout: global.clearTimeout,
            setInterval: global.setInterval,
            clearInterval: global.clearInterval,
            requestAnimationFrame: undefined,
            cancelAnimationFrame: undefined
        };
    }
    else {
        const noop = () => { };
        const noopWithReturn = () => 0;
        return {
            setTimeout: noopWithReturn,
            clearTimeout: noop,
            setInterval: noopWithReturn,
            clearInterval: noop,
            requestAnimationFrame: undefined,
            cancelAnimationFrame: undefined
        };
    }
};
const timers = getTimerFunctions();
export class ResourceManager {
    constructor() {
        this.resources = new Map();
        this.globalResources = new Set();
        this.cleanupCallbacks = new Map();
    }
    setTimeout(componentId, callback, delay, metadata) {
        const id = timers.setTimeout(() => {
            this.removeResource(componentId, 'timer', id);
            callback();
        }, delay);
        this.addResource(componentId, {
            type: 'timer',
            id,
            cleanup: () => timers.clearTimeout(id),
            metadata
        });
        return id;
    }
    setInterval(componentId, callback, delay, metadata) {
        const id = timers.setInterval(callback, delay);
        this.addResource(componentId, {
            type: 'interval',
            id,
            cleanup: () => timers.clearInterval(id),
            metadata
        });
        return id;
    }
    requestAnimationFrame(componentId, callback, metadata) {
        if (!timers.requestAnimationFrame) {
            return this.setTimeout(componentId, () => callback(Date.now()), 16, metadata);
        }
        const id = timers.requestAnimationFrame((time) => {
            this.removeResource(componentId, 'animationFrame', id);
            callback(time);
        });
        this.addResource(componentId, {
            type: 'animationFrame',
            id,
            cleanup: () => timers.cancelAnimationFrame?.(id),
            metadata
        });
        return id;
    }
    clearTimeout(componentId, id) {
        timers.clearTimeout(id);
        this.removeResource(componentId, 'timer', id);
    }
    clearInterval(componentId, id) {
        timers.clearInterval(id);
        this.removeResource(componentId, 'interval', id);
    }
    cancelAnimationFrame(componentId, id) {
        if (timers.cancelAnimationFrame) {
            timers.cancelAnimationFrame(id);
        }
        else {
            timers.clearTimeout(id);
        }
        this.removeResource(componentId, 'animationFrame', id);
    }
    addEventListener(componentId, target, type, listener, options) {
        if (target && typeof target.addEventListener === 'function') {
            target.addEventListener(type, listener, options);
            const resourceId = `${type}-${Date.now()}-${Math.random()}`;
            this.addResource(componentId, {
                type: 'eventListener',
                id: resourceId,
                cleanup: () => {
                    if (target && typeof target.removeEventListener === 'function') {
                        target.removeEventListener(type, listener, options);
                    }
                },
                metadata: { target, type, options }
            });
        }
    }
    registerDOMElement(componentId, element, cleanup) {
        if (typeof document !== 'undefined' && element && element.parentNode) {
            const resourceId = `dom-${Date.now()}-${Math.random()}`;
            this.addResource(componentId, {
                type: 'domElement',
                id: resourceId,
                cleanup: () => {
                    if (cleanup) {
                        cleanup();
                    }
                    if (element && element.parentNode && typeof element.parentNode.removeChild === 'function') {
                        element.parentNode.removeChild(element);
                    }
                },
                metadata: { element }
            });
        }
    }
    registerReactRoot(componentId, root, unmountFn) {
        this.addResource(componentId, {
            type: 'reactRoot',
            id: `react-root-${componentId}`,
            cleanup: unmountFn,
            metadata: { root }
        });
    }
    registerCleanup(componentId, cleanup) {
        if (!this.cleanupCallbacks.has(componentId)) {
            this.cleanupCallbacks.set(componentId, []);
        }
        this.cleanupCallbacks.get(componentId).push(cleanup);
    }
    registerGlobalResource(resource) {
        this.globalResources.add(resource);
    }
    addResource(componentId, resource) {
        if (!this.resources.has(componentId)) {
            this.resources.set(componentId, new Set());
        }
        this.resources.get(componentId).add(resource);
    }
    removeResource(componentId, type, id) {
        const componentResources = this.resources.get(componentId);
        if (componentResources) {
            const toRemove = Array.from(componentResources).find(r => r.type === type && r.id === id);
            if (toRemove) {
                componentResources.delete(toRemove);
            }
        }
    }
    cleanupComponent(componentId) {
        const componentResources = this.resources.get(componentId);
        if (componentResources) {
            componentResources.forEach(resource => {
                try {
                    resource.cleanup();
                }
                catch (error) {
                    console.error(`Error cleaning up ${resource.type} resource:`, error);
                }
            });
            this.resources.delete(componentId);
        }
        const callbacks = this.cleanupCallbacks.get(componentId);
        if (callbacks) {
            callbacks.forEach(callback => {
                try {
                    callback();
                }
                catch (error) {
                    console.error('Error executing cleanup callback:', error);
                }
            });
            this.cleanupCallbacks.delete(componentId);
        }
    }
    cleanupGlobal() {
        this.globalResources.forEach(resource => {
            try {
                resource.cleanup();
            }
            catch (error) {
                console.error(`Error cleaning up global ${resource.type} resource:`, error);
            }
        });
        this.globalResources.clear();
    }
    cleanupAll() {
        for (const componentId of this.resources.keys()) {
            this.cleanupComponent(componentId);
        }
        this.cleanupGlobal();
    }
    getStats() {
        const resourceCounts = {};
        for (const resources of this.resources.values()) {
            resources.forEach(resource => {
                resourceCounts[resource.type] = (resourceCounts[resource.type] || 0) + 1;
            });
        }
        return {
            componentCount: this.resources.size,
            resourceCounts,
            globalResourceCount: this.globalResources.size
        };
    }
}
export const resourceManager = new ResourceManager();
//# sourceMappingURL=resource-manager.js.map