/**
 * Basic base object for BasisFramework applications.
 * @class Basis
 * @author Adam Presley
 */
var Basis = function()
{
	this.log = function(value)
	{
		if ("console" in window)
		{
			console.log(value);
		}
	};
	
	this.framework = {
		ajaxProxyUrl: "/com/basisframework/ajaxProxy.cfm"
	};
};

/**
 * Basic AJAX handling. Doesn't assume any particular JavaScript framework.
 * The config object can take the following keys:
 * 		- url -- Path to the remote page
 * 		- data -- Object of POST data
 *		- scope -- Scope in which to call success and failure handlers
 *		- success -- Callback function for success
 *		- failure -- Callback function for failure
 * 
 * @class Basis.Ajax
 * @extends Basis
 * @author Adam Presley
 * @param Object config
 */
Basis.Ajax = function(config)
{
	this.objectToQueryString = function(o)
	{
		var result = "";
		var it = "";
		
		for (it in o) { result += "" + it + "=" + escape(o[it]) + "&"; }
		result = result.substring(0, result.length - 1);
		return result;
	};
	
	var http = null;
	var o = null;
	var __this = this;
	
	if (window.XMLHttpRequest)
	{
		http = new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		http = new ActiveXObject("Microsoft.XMLHTTP");
	}
	
	if (!("type" in config)) { config.type = "POST"; }
	
	if (config.type === "POST") 
	{
		http.open("POST", config.url, true);
	}
	else
	{
		http.open("GET", config.url + "?" + this.objectToQueryString(config.data || {}), true);
	}
	
	http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	http.setRequestHeader("X-Requested-With", "XMLHttpRequest");
	
	http.onreadystatechange = function() 
	{
		switch (http.readyState)
		{
			case 4:
				if (http.status === 200)
				{
					o = eval("(" + http.responseText + ")");

					if ("success" in config)
					{
						if ("scope" in config) 
						{
							config.success.call(config.scope, o);
						}
						else
						{
							config.success(o);
						}
					}
				}
				else
				{
					if ("failure" in config)
					{
						if ("scope" in config)
						{
							config.failure.call(config.scope, http.responseText);
						}
						else
						{
							config.failure(http.responseText);
						}
					}
				}
				break;
		}
	};
	
	if (config.type === "POST")
	{
		http.send(this.objectToQueryString(config.data || {}));
	}
	else
	{
		http.send(null);
	}
};
Basis.Ajax.prototype = new Basis();

/**
 * Basic implementation of the Observer pattern.
 * @class Observer
 * @author Adam Presley
 */
Basis.Observer = function() 
{
	window.__observerSettings = {
		listeners: {}
	};
 
	/**
	 * This method registers a handler for a specified event.
	 * @author Adam Presley
	 * @param {String} eventName
	 * @param {Function} handler
	 * @param {Object} scope
	 */
	this.subscribe = function(eventName, handler, scope) 
	{
		var l = window.__observerSettings.listeners;
		var definition = {
			eventName: eventName,
			handler: handler,
			scope: (scope || undefined)
		};
 
		if (eventName in l)
		{
			l[eventName].push(definition);
		}
		else
		{
			l[eventName] = [ definition ];
		}
	};
 
	/**
	 * Tells the object to publish an event by name, sending a series of parameters
	 * along with the message for any subscribers to pick up.
	 *
	 * @author Adam Presley
	 * @param {String} eventName
	 * @param {Object} params
	 */
	this.publish = function(eventName, params)
	{
		var i = 0;
		var params = params || {};
		var l = window.__observerSettings.listeners;
 
		if (eventName in l)
		{
			for (i = 0; i < l[eventName].length; i++)
			{
				if ("scope" in l[eventName][i] && l[eventName][i].scope !== undefined)
				{
					l[eventName][i].handler.call(l[eventName][i].scope, params);
				}
				else
				{
					l[eventName][i].handler(params);
				}
			}
		}
	};
};
Basis.Observer.prototype = new Basis();

/**
 * A base object for service management
 * @author Adam Presley
 * @class Basis.Service
 * @extends Basis.Observer
 */
Basis.Service = function()
{
	/**
	 * Sends an AJAX call
	 */
	this.SendRequest = function(config)
	{
		var __this = (config.scope || this);
		var action = this.__config.section + "." + config.method;
		
		config.request = config.request || {};
		config.request.action = action;
		
		Basis.Ajax({
			url: this.framework.ajaxProxyUrl,
			data: config.request,
			scope: __this,
			success: config.success,
			failure: config.failure
		});
	};
};
Basis.Service.prototype = new Basis.Observer();

