/**
 * @private
 */
Ext.define('Ext.dom.GarbageCollector', {
    singleton: true,
 
    interval: 30000,
 
    constructor: function() {
        var me = this;
        me.collect = Ext.Function.bind(me.collect, me);
        me.resume();
    },
 
    // private 
    // Garbage collection - uncache elements/purge listeners on orphaned elements 
    // so we don't hold a reference and cause the browser to retain them 
    collect: function() {
        var me = this,
            cache = Ext.cache,
            eid, dom, el, t;
 
        if (!Ext.enableGarbageCollector) {
            me.pause();
        } else {
            for (eid in cache) {
                if (!cache.hasOwnProperty(eid)) {
                    continue;
                }
 
                el = cache[eid];
 
                // Skip document and window elements 
                if (el.skipGarbageCollection) {
                    continue;
                }
 
                dom = el.dom;
 
                //<debug> 
                // Should always have a DOM node 
                if (!dom) {
                    Ext.Error.raise('Missing DOM node in element garbage collection: ' + eid);
                }
                //</debug> 
 
                // Do not attempt to garbage collect documents and windows. 
                if (Ext.isGarbage(dom)) {
                    el.clearListeners();
                    delete cache[eid];
                }
            }
            //<feature legacyBrowser> 
            // Cleanup IE Object leaks 
            if (Ext.isIE9m) {
                t = {};
                for (eid in cache) {
                    if (cache.hasOwnProperty(eid)) {
                        t[eid] = cache[eid];
                    }
                }
                cache = Ext.cache = t;
            }
            //</feature> 
 
            me.lastTime = Ext.now();
        }
    },
 
    pause: function() {
        clearTimeout(this.timerId);
    },
 
    resume: function() {
        var me = this,
            lastTime = me.lastTime;
 
        if (lastTime && (Ext.now() - lastTime > me.interval)) {
            me.collect();
        }
 
        me.timerId = Ext.interval(me.collect, me.interval);
    }
});