gCjs.util.Delegate = function(o, f, ef) 
{
	this._o = o;
	this._f = f;
	if (ef!=undefined) {
    	this._ef = ef;	
    	this._a = [].splice.call(arguments,3);	    
	} else {
    	this._a = [].splice.call(arguments,2);
	}
	this._fProxy = gCjs.util.Delegate.create.apply(this, [this._o].concat([this._f], this._a));
	// test if there is a onError callback
	if (ef!=undefined) {
	    this._efProxy = gCjs.util.Delegate.create.apply(this, [this._o].concat([this._ef], this._a));
	}	
}

gCjs.util.Delegate.prototype.setArguments = function()
{
	if (arguments.length > 0)
	{
		this._a = arguments;
		this._fProxy.a = this._a;
        if (this._efProxy != undefined) this._efProxy.a = this._a;
	}
}

gCjs.util.Delegate.prototype.execute = function()
{
	this._fProxy();
}

gCjs.util.Delegate.prototype.executeError = function()
{
    if (this._efProxy != undefined) {
	    this._efProxy();        
    } else {
        alert("An error occured, please reload the page.");
    }
}

gCjs.util.Delegate.create = function(o, f) 
{
	var _f = function()
	{	
		var scope = arguments.callee.oScope;
		var ff = arguments.callee.f;
		return ff.apply(scope, jQuery.makeArray(arguments).concat(jQuery.makeArray(arguments.callee.a)));
	};
	_f.oScope = o;
	_f.f = f;
	_f.a = [].splice.call(arguments,2);
	return _f;
}

gCjs.util.CustomEvent = function(type, oScope) {

     /**
      * The type of event, returned to subscribers when the event fires
      * @property type
      * @type string
      */
     this.type = type;

     /**
      * The scope the the event will fire from by default.  Defaults to the window 
      * obj
      * @property scope
      * @type object
      */
     this.scope = oScope || window;

     /**
      * The subscribers to this event
      * @property subscribers
      * @type Subscriber[]
      */
     this.subscribers = [];

};

gCjs.util.EventBroadcaster = function() {

    var _listeners = new Object();

    return {
        
        broadcastMessage: function(){
        	var args = [];
        	for(var i=0;i<arguments.length;i++) args[i]=arguments[i];
        	var oListened = args.shift();
        	var eventName = args.shift();
        	var list = this._listeners[oListened];
        	var max = list.length;
        	for(var i=0;i<max;++i){
        	    var f = list[i].fn;
        	    var o = list[i].listener;
        	    o[f].apply(list[i],args);
        	}
        },

        /**
         * Appends an event handler
         *
         * @method addListener
         *
         */
        addEventListener: function(oListener, oListened, sEvent, fnHandler) {
            if (this._listeners[oListened] == undefined) {
                this._listeners[oListened] = [];
            }
            if (!fnHandler) fnHandler = sEvent;
            this._listeners[oListened].push({listener:oListener,event:sEvent,fn:fnHandler})
        	return true;
        },

        removeEventListener: function(oListener, oListened, sEvent){
        	var list = this._listeners[oListened];
        	var i = list.length;
        	while(i--){
        		if(list[i].listener==oListener && list[i].event==sEvent) {
        			list.splice(i,1);
        			return true;
        		}
        	}
        	return false;
        }
    }
};

if(!gCjs.util.Event) {
    
    gCjs.util.Event = {
        isReady: false,
        onReadyDomEvents: []
    }
    
    gCjs.util.Event.ready = function(f) {
        // If the DOM is already ready
        if (gCjs.util.Event.isReady) {
            // Execute the function immediately
            switch(typeof f) {
                case 'string':
                    eval(f);
                break;
                case 'function':
                    f.apply(document);
                break;
            }
        // Otherwise add the function to the wait list
        } else {
            gCjs.util.Event.onReadyDomEvents.push(f);
        }
    }

    gCjs.util.Event.onReadyDom = function() {
        gCjs.util.Event.isReady = true;
        if (gCjs.util.Event.onReadyDomEvents) {
            for (var i in gCjs.util.Event.onReadyDomEvents) {
                var f = gCjs.util.Event.onReadyDomEvents[i];
                switch(typeof f) {
                    case 'string':
                        eval(f);
                    break;
                    case 'function':
                        f.apply(document);
                    break;
                }
            }
        }
    }
    
}

//use jquery ready to fire onReadyDom();
$(document).ready(
	function() {
        gCjs.util.Event.onReadyDom();
	}
);

gCjs.register("event", gCjs.util.Event);