/* Abtraction of AJAX.Responders to allow for arbitrary collections of responders to arbitrary events.
 *
 *
 */

GenericEventResponders = new Class.create();

Object.extend(GenericEventResponders.prototype, {

    initialize: function(respondersToAdd) {
        this.responders = new Array();
        if (respondersToAdd) {
            this.registerMany(respondersToAdd); 
        }
    },
 
    _each: function(iterator) {
        this.responders._each(iterator);
    },

    register: function(responderToAdd) {
        if (!this.include(responderToAdd))
            this.responders.push(responderToAdd);
    },

    registerMany: function(respondersToAdd) {
        var me = this;
        $A(respondersToAdd).each(function(responder) {
            me.register(responder);
        });
    },
    
    unregister: function(responderToRemove) {
        this.responders = this.responders.without(responderToRemove);
    },

    dispatch: function() {
        var args = $A(arguments), callback = args.shift();
        if (args[0] == null) { args[0] = new Object(); }
        this.each(function(responder) {
            if (responder != null && responder[callback] 
                && typeof responder[callback] == 'function') {
                try {
                    responder[callback].apply(responder, args);
                } catch (e) { throw e; }
            }
        });
    }
    
});
Object.extend(GenericEventResponders.prototype, Enumerable);
GenericEventResponders.prototype.tell =
    GenericEventResponders.prototype.dispatch;



/*
 * GenericEventManager
 * Stores global data about event types, manages the firing of idle events
 *
 */

var GenericEventManager = new Object();

Object.extend(GenericEventManager, {
	realEventTypes: ['load', 'unload', 'abort', 'error', 'select', 'change', 'submit', 'reset', 'focus', 'blur', 'resize', 'scroll', 'click', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
	syntheticEventTypes: ['onDraw', 'onClear', 'onRedraw', 'onTimerEvent', 'onComplete', 'onSuccess', 'onFailure', 'onException', 'onError', 'onValueChange', 'onIdle'],
	
    idle_observers: new GenericEventResponders(),
	
    addIdleObserver: function(observer) {
        this.idle_observers.register(observer);
    },
    
	startIdler: function(time) {
        this.idle_time = time || 0.5;
        this.idle_processing = 0;
        this.idle_interval = setInterval(
            this.onTimerEvent.bind(this), this.idle_time * 1000);
    },     
    onTimerEvent: function() {
        if (!this.idle_processing) {
            this.idle_processing = 1;
            this.idle_observers.tell('onIdle', { });
            this.idle_processing = 0;
        }
    }

});




// Holds page wide data structures
var GenericPage = new Object();

Object.extend(GenericPage, {
    els: new Array(),
	widgets: new Object(),
    widget_responders: new GenericEventResponders(),
    next_widget_id: 1,
	elems: new Object(),	
    
    addToPage: function(obj, name) {
        if (!name) { name = this.next_widget_id++; }
        this.widgets[name] = obj;
        this.widget_responders.register(obj);
    },
    
    tell: function(method, args) {
        this.widget_responders.tell(method, args);
    }    

});


window.onunload = function(evt) {
    clearInterval(GenericEventManager.idle_interval);
    GenericEventManager.idle_observers = null;
    GenericPage.widget_responders = null;
    Element.unelAll();
    //Element.unelDeep(document.body);
};





