/**
 * @fileoverview AJAXCode.js
 * 
 * Repository for AJAX functions including the XMLHTTP Object manipulation,
 * Parameter and Utility functions and the handler functions.
 * 
 * @author Chris 'Chopper' Vincent (19 May 2008)
 */

/**
 * HTTP Object global variable
 */
var httpObject = null;

/***********************************************************************/

/**
 * Utils class to cover any useful utility functions
 */
function Utils() {};

/**
 * Changes the cursor style to busy (hour glass pointer)
 */
Utils.setCursorBusy = function()
{
	document.body.style.cursor = "wait";
}

/**
 * Changes the cursor style to the default pointer
 */
Utils.setCursorDefault = function()
{
	document.body.style.cursor = "default";
}

/**
 * Converts a string to XML format 
 * 
 * @param [String] xmlString The string to be converted
 * @return [DOM] XML version of the string passed in
 */
Utils.convertStringToXML = function(xmlString)
{
	return (new DOMParser()).parseFromString(xmlString, "text/xml");
}

/**
 * Retrieves a node value or a blank string if the node is null
 * 
 * @param [DOM] dom XML Document Object Model
 * @param [String] nodeName Name of the node to retrieve the value of
 * @return The value of the node specified or a blank string if no value/node
 */
Utils.getNodeValue = function(dom, nodeName)
{
	var node = dom.getElementsByTagName(nodeName)[0].firstChild;
	var nodeValue = "";
	if ( null != node )
	{
		nodeValue = node.nodeValue;
	}
	return nodeValue;
}

/***********************************************************************/

/**
 * Parameters class to enable parameters to be added to service calls
 */
function Parameters() {};
/**
 * List of parameters which will be a 2D Array.  Each array element will
 * represent a parameter and is an Array object as well with two elements.
 * The first represents the parameter name and the second represents the
 * parameter value.
 */
Parameters.list = null;

/**
 * Function to initialise/reset the parameter list.  This should be called
 * prior to adding parameters to a service call. 
 */
Parameters.initialise = function()
{
	this.list = [];
}

/**
 * Function to add a parameter to the list by appending a new element to the
 * end of the existing list.
 * 
 * @param name [String] The name of the parameter
 * @param value [String] The value of the parameter
 */
Parameters.addParameter = function(name, value)
{
	var param = [name, value];
	this.list.push(param);
}

/***********************************************************************/

/**
 * Services class to hold the necessary AJAX functions needed to call
 * and handle server side calls.
 */
function Services() {};

/**
 * Returns an XMLHTTP Object
 * 
 * @return [Object] the XML HTTP Object
 */
Services.GetXmlHttpObject = function()
{
	var xmlHttp=null;
	try
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}
	catch (e)
	{
		//Internet Explorer
		try
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e)
		{
			xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;
}

/**
 * Function makes a HTTP call to a specific service method.
 * 
 * @param string root Path back to the root directory from the calling file
 * @param string method The name of the method to be called
 * @param object handler The handler object for the service call. An onSuccess method must exist on this object.
 * @param boolean async Flag whether or not services are asyncronous, defaults to true if not specified
 */
Services.callService = function(root, method, handler, async, setCursor)
{
	// Get the HTTP object
	httpObject = Services.GetXmlHttpObject();
	if ( httpObject != null && method != null && handler != null ) 
	{
		// Check if the async parameter has been specified
		var _async = (null == async) ? true : async;
		
		// Generate the url, passing in the method name specified by the calling function
		if ( null == root || root.length == 0 ) root = "../";
		var url = root + "Request.php";
		var params = "method=" + method;

		// Loop through the parameters list and add them to the url
		if ( Parameters.list != null && Parameters.list.length > 0 )
		{
			for ( var i=0, l=Parameters.list.length; i<l; i++ )
			{
				params = params + "&" + Parameters.list[i][0] + "=" + Parameters.list[i][1];
			}
		}

		// Open the object and send the request
		httpObject.onreadystatechange = handler.onSuccess;
		httpObject.open("POST", url, _async);
      	httpObject.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
      	httpObject.setRequestHeader("Content-length", (Parameters.list.length + 1) );
      	httpObject.setRequestHeader("Connection", "close");
      	httpObject.send(params);

		// Set the cursor to busy
		if ( setCursor != false )
		{
			Utils.setCursorBusy();
		}
	}
}

/**
 * Indicates whether or not the HTTP call has completed
 * 
 * @return [boolean] True if the httpObject is in a complete state, else false
 */
Services.callComplete = function()
{
	var blnCallComplete = false;
	if ( httpObject.readyState == 4 || httpObject.readyState == "complete" )
	{
		blnCallComplete = true;
	}
	return blnCallComplete;
}

/**
 * Returns the request text from the HTTP Object.  If the status code is not 200 ("OK")
 * then an appropriate error message is alerted.
 * 
 * @return [string] the request text or null if there was a problem
 */
Services.getRequestText = function()
{
	var requestText = null;
	if ( Services.callComplete() )
	{
		// Check for status code of 200 (OK)
		if ( httpObject.status == 200 )
		{
			// Return the responseText
			requestText = httpObject.responseText;
		}
		else
		{
			// Handle the error message
			Utils.setCursorDefault();
			alert("Error: " + httpObject.status + " (" + httpObject.statusText + ")" );
		}
	}
	return requestText;
}

/**
 * Returns the request XML from the HTTP Object.  If the status code is not 200 ("OK")
 * then an appropriate error message is alerted.
 * 
 * @return [Object] the request XML (DOM) Object or null if there was a problem
 */
Services.getRequestXML = function()
{
	var requestXML = null;
	if ( Services.callComplete() )
	{
		// Check for status code of 200 (OK)
		if ( httpObject.status == 200 )
		{
			// Return the responseText
			requestXML = httpObject.responseXML;
		}
		else
		{
			// Handle the error message
			Utils.setCursorDefault();
			alert("Error: " + httpObject.status + " (" + httpObject.statusText + ")" );
		}
	}
	return requestXML;
}