/* 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);
    },
    finish: function() {
        this.tell('onPageFinish');
    },

    // adapted from ufo.js
	setupDomLoad: function(id) {
		if (typeof document.addEventListener != "undefined") {
			document.addEventListener("DOMContentLoaded", function() { 
                GenericPage.tell('onDraw');
            } , null); // Mozilla only
		}
        else {
             GenericPage.tell('onDraw');
        }
	},
    
    
    getHeight: function(minheight) {
        var module_maxheight = minheight || 0;
        EL.eachChild(document.body, function(child) {
            if (
                child.tagName == 'DIV' && 
                EL.visible(child)
            ) {
                //var pos = Position.cumulativeOffset(child);
                //var height = pos[1] + EL.getHeight(child);
                var height = child.offsetTop + child.offsetHeight;
                if (height > module_maxheight) { module_maxheight = height; }
            }
        });
        return module_maxheight;
    },
    
    popup: function(url, args) {
        var defaults = {
            height: 600,
            width: 475,
            top: 10,
            left: 10,
            resizable: 'yes',
            scrollbars: 'yes',
            status: 'no',
            toolbar: 'no',
            menubar: 'no',
            name: 'pop'
        };
        args = Object.applyDefaults(args, defaults);
        
        var specs =
            'height='+args.height+
            ',width='+args.width+
            ',top='+args.top+
            ',left='+args.left+
            ',resizable='+args.resizeable+
            ',scrollbars='+args.scrollbars+
            ',status='+args.status+
            ',toolbar='+args.toolbar+
            ',menubar='+args.menubar+
            ',location='+url;
        //alert(f);
        var win = window.open(url, args.name, specs);
        if (!win) { window.alert('Please deactivate your popup blocker to view this page.'); }
        return;
    }

});

// setup finishers
GenericPage.addToPage({
    onPageFinish: function() {
        GenericPage.setupDomLoad('GenericPage_finisher');
    }
}, 'finisher');


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




