// Custom Event Dispatcher
// Requires: window manager (AWindowManager)

// Event type flags (should be powers of 2)
var ET_NONE      = 0;
var ET_REGULAR   = 1;
var ET_DEFAULT   = 2;
var ET_IMPORTANT = 4;

// Helper storage class for event handlers storage
// Can be compared using .Compare method
var AEventHandler = Class.create({
	initialize: function(fCallback, oThisObject) {
		this.fCallback_ = fCallback;
		this.oThisObject_ = oThisObject;
	},
	Compare: function(oAnotherHandler) {
		return (this.fCallback_ == oAnotherHandler.fCallback_ &&
			this.oThisObject_ == oAnotherHandler.oThisObject_);
	},
	Callback: function() { return this.fCallback_; },
	ThisObject: function() { return this.oThisObject_; }
});

/*
 * oEventData params:
 * 	bMutable - boolean. Says whether the "CHANGE" event should NOT affect modification status of the issuer window.
 */
var AEvent = Class.create({
	initialize: function(sEventName, oEventData, oControl, bDispatchImmediately) {
		this.nEventType_ = ET_NONE;
		sEventName=String(sEventName).toUpperCase();
		if (!sEventName) {
			alert("Event name is not defined or empty, please check event 'type' attribute. ");
			return;
		}
		this.sEventName_=sEventName;
		this.oEventData_ = oEventData;
		if (!oControl) {
			this.oControl_ = null;
			this.sControlID_ = "";
		} else {
			if (typeof(oControl) == "string") {
				this.sControlID_ = oControl;
				var elControl = $(oControl);
				if (!elControl) return; // node not initialized or already removed
				this.oControl_ = (elControl.JSControl) ? elControl.JSControl : null;
			} else { // this is a kosher control
				this.oControl_ = oControl;
				this.sControlID_ = this.oControl_.ID();
			}
		}
		this.bPropogation_ = true;
		// post event to global event manager
		if (bDispatchImmediately || typeof(bDispatchImmediately) == "undefined") {
			this.bPosted_ = true;
			this.post();
		}
	},
	Post: function() {
		if (this.bPosted_) throw new Error("Event already posted! ");
		else this.post();
	},
	// internal method
	post: function() {
		AWindow.postEvent(this);
	},
	Stop: function() { this.bPropogation_ = false; },
	// Getters
	Name: function() { return this.sEventName_; },
	Type: function() { return this.nEventType_; },
	SetType: function(nEventType) { this.nEventType_ = nEventType; },
	Data: function() { return this.oEventData_; },
	SetData: function(data) { this.oEventData_ = data; },
	Emitter: function() { return this.oControl_; },
	EmitterID: function() { return this.sControlID_; },
	Propogation: function() { return this.bPropogation_; }
});

function SubscribeOnEvent(sEventName, sWindowID, fCallback, oThisObject) {
	var win = (sWindowID == "document") ? GDocumentInstance : GWindowManager.GetWindow(sWindowID);
	win.Subscribe(sEventName, fCallback, oThisObject);
}

function UnsubscribeFromEvent(sEventName, sWindowID, fCallback, oThisObject) {
	var win = (sWindowID == "document") ? GDocumentInstance : GWindowManager.GetWindow(sWindowID);
	win.Unsubscribe(sEventName, fCallback, oThisObject);
}

