if ('coss' in window) {
if ('HtmlNotificationManager' in coss) {


coss.Conduit = function () {};

coss.Conduit.prototype.getAjaxTunnel = function () {
	if (this._conduit.ajaxTunnel == null) {
		this._conduit.ajaxTunnel = new coss.AjaxTunnel();
		this._conduit.ajaxTunnel.construct();
	}
	
	return this._conduit.ajaxTunnel;
};

coss.Conduit.prototype.addDataBinder = function (aBinder) {
	this._conduit.dataBinders.push(aBinder);
};

coss.Conduit.prototype.bindData = function (aData) {
	var i;
	
	for (i = 0; i < this._conduit.dataBinders.length; i++) {
		//call data binder function in global/window scope
		this._conduit.dataBinders[i].apply(window, [aData]);
	}
};

coss.Conduit.prototype.construct = function () {
	this._conduit = {
		dataBinders : [],
		ajaxTunnel : null,
		iframeTunnel : null
	};
};




coss.AjaxTunnel = function () {};

coss.AjaxTunnel.prototype.execute = function (aData, aOptions) {
	var url, urlQs, matches, data, method;
	
	//resolve url
	url = (aOptions && 'url' in aOptions) ? aOptions.url : this.getUrl();
	urlQs = '';
	matches = url.match(/\?([^#]+)/);
	if (matches != null && matches.length == 2) {
		urlQs = matches[1];
		url = url.replace(/\?(.+)/, '');
	}
	if (url == null) {
		throw "Invalid URL: '" + this._ajaxTunnel.url + "'";
	}
	
	//resolve method
	method = (aOptions && 'method' in aOptions) ? aOptions.method : this.getMethod();
	
	//resolve data
	data = aData;
	if (urlQs != '') data += '&' + urlQs;
	
	this.dispatchEvent('begin');
	
	jQuery.ajax({
		'context' : this,
		'dataType' : 'json',
		'data' : data,
		'type' : method,
		'url' : url,
		'success' : this._ajaxTunnel.jquerySuccessHandler,
		'error' : this._ajaxTunnel.jqueryErrorHandler
	});
};

coss.AjaxTunnel.prototype.getMethod = function () {
	return this._ajaxTunnel.method;
};

coss.AjaxTunnel.prototype.setMethod = function (aMethod) {
	this._ajaxTunnel.method = aMethod;
};

coss.AjaxTunnel.prototype.getUrl = function () {
	return this._ajaxTunnel.url;
};

coss.AjaxTunnel.prototype.setUrl = function (aUrl) {
	this._ajaxTunnel.url = aUrl;
};

coss.AjaxTunnel.prototype.addEventListener = function (aEventType, aFunction) {
	if ((aEventType in this._ajaxTunnel.eventListeners) == false) {
		throw "Unknown event type: '" + aEventType + "'.";
	}
	
	this._ajaxTunnel.eventListeners[aEventType].push(aFunction);
};

coss.AjaxTunnel.prototype.dispatchEvent = function (aEventType, aEvent) {
	var i;
	
	if ((aEventType in this._ajaxTunnel.eventListeners) == false) {
		throw "Unknown event type: '" + aEventType + "'.";
	}
	
	for (i = 0; i < this._ajaxTunnel.eventListeners[aEventType].length; i++) {
		this._ajaxTunnel.eventListeners[aEventType][i].apply(this, [aEvent]);
	}
};

coss.AjaxTunnel.prototype.construct = function () {
	this._ajaxTunnel = {
		method : null,
		url : null,
		
		eventListeners : {
			'begin' : [],
			'end' : []
		},
		
		jquerySuccessHandler : function (aJson) {
			this.dispatchEvent('end', {
				error : null,
				data : aJson
			});
		},
		
		jqueryErrorHandler : function (aXhr, aStatus) {
			this.dispatchEvent('end', {
				error : {type : aStatus},
				data : null
			});
		}
	};
	
	this.setMethod('post');
	this.setUrl('index.php');
};


coss.ModuleHelper = function () {};

coss.ModuleHelper.prototype.construct = function (aModule) {
	this._moduleHelper = {
		parent : aModule
	};
};

coss.ModuleHelper.prototype.getParent = function () {
	return this._moduleHelper.parent;
};


coss.ModuleModel = function () {
	if (!(arguments.length == 1 && arguments[0] == coss.ModuleHelper)) this.construct.apply(this, arguments);	
};
coss.extend(coss.ModuleModel, coss.HashMap);




coss.Module = function () {};

coss.Module.prototype.handleMainConduitAjaxEnd = function (aResult) {
	if (aResult.error == null) {
		gModule.getMainConduit().bindData(aResult.data);
	}
	
	else {
		gModule.getMainConduit().bindData({
			system : {
				notifications : [
					{
						body :
							"An error has ocurred, please try again."
					}
				]
			}
		});
	}
};

coss.Module.prototype.getNotificationManager = function () {
	if (this._module.notificationManager == null) this._module.notificationManager = new coss.HtmlNotificationManager();
	return this._module.notificationManager;
};

coss.Module.prototype.getMainConduit = function () {
	return this._module.mainConduit;
};

coss.Module.prototype.getHashManager = function () {
	if (this._module.hashManager == null) this._module.hashManager = new coss.HashManager();
	return this._module.hashManager;
};

coss.Module.prototype.getPendingData = function () {
	return this._module.pendingData;
};

coss.Module.prototype.setPendingData = function (aData) {
	this._module.pendingData = aData;
};

coss.Module.prototype.getHelper = function (aCode) {
	var i;
	for (i = 0; i < this._module.helpers.length; i++) {
		if (this._module.helpers[i].code == aCode) {
			return this._module.helpers[i].helper;
		}
	}
	throw "Unknown helper with code: '" + aCode + "'";
};

coss.Module.prototype.getAllHelpers = function () {
	return this._module.helpers.concat([]); //copy
};

coss.Module.prototype.setHelper = function (aCode, aHelper) {
	this._module.helpers.push({
		code : aCode,
		helper : aHelper
	});
};

coss.Module.prototype.delegateToHelpers = function (aFunctionName, aArgs) {
	var i, helpers;
	
	helpers = this.getAllHelpers();
	for (i = 0; i < helpers.length; i++) {
		if (aFunctionName in helpers[i].helper) {
			helpers[i].helper[aFunctionName].apply(helpers[i].helper, aArgs);
		}
	}
};

coss.Module.prototype.resolveHelpers = function () {
	
};

coss.Module.prototype.getModel = function () {
	if (this._module.model == null) this._module.model = new coss.ModuleModel();
	return this._module.model;
};

coss.Module.prototype.hookUp = function () {
	this.getMainConduit().addDataBinder(function (aData) {
		var notifications = coss.arrayGet(aData, 'system.notifications');
		if (notifications && notifications.length > 0) {
			for (i = 0; i < notifications.length; i++) {
				gModule.getNotificationManager().queue(notifications[i]);
			}
		}
	});
};

coss.Module.prototype.init = function () {
	this.resolveHelpers();
};

coss.Module.prototype.construct = function () {
	var t;
	
	this._module = {
		pendingData : null,
		hashManager : null,
		helpers : [],
		model : null
	};
	
	t = new coss.Conduit();
	t.construct();
	this._module.mainConduit = t;
	
	t = this.getMainConduit().getAjaxTunnel();
	t.addEventListener('end', this.handleMainConduitAjaxEnd);
	
	$(document).bind('ready', function() {
		gModule.hookUp();
		gModule.getMainConduit().bindData(gModule.getPendingData());
	});
};




} else throw "Package coss-lib-notification.js must be included.";
} else throw "Package coss.js must be included.";
