/**
 * Constuctor for AJAX calls to server.
 * @param strUrl The url to post to.
 * @param fPostProcess optional arg for post processing. 
 * 							 If specficied, the call is made asynchronosly.
 */
function AJAX(strUrl, fPostProcess)
{
	this.m_oHttp = prepareXMLHttp();
	this.m_strUrl = strUrl;
	this.m_fPostProcess = fPostProcess;
	this.m_bAsync = (fPostProcess != null);
	this.m_bStopOnError = true;
	this.m_bStopOnWarning = true;
	this.m_bDebug = false;
	this.m_params = "";
	this.m_returnType = "text";
	this.m_lastErrorMessage = null;
	this.m_lastWarningMessage = null;
	this.m_charset = "ISO-8859-1";
	this.m_bAddTimestamp = false;

	if (this.m_bAsync)
	{
		var oHttp = this;
		oHttp.m_oHttp.onreadystatechange = function()
		{
			oHttp.handleHttpResponse();
		};
	}
}

/**
 * Sends the POST to the server and returns the response.
 * @return The response root element as text from the http post. 
 * 		   May be null if failure has occured, or call is asyndchrounous.
 */
AJAX.prototype.doPost = function()
{
	this.m_oHttp.open("POST", this.m_strUrl, this.m_bAsync);
	this.m_oHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=" + this.m_charset);
	this.m_oHttp.setRequestHeader("Content-length", this.m_params.length);
	//this.m_oHttp.setRequestHeader("Connection", "close");
	try
	{
		this.m_oHttp.send(this.m_params.charAt(0) == "&" ? this.m_params.substring(1) : this.m_params);
		if (!this.m_bAsync)
		{
			return this.handleHttpResponse();
		}
		return null;
	}
	catch (e)
	{
		alert("Unable to communicate with server. Please try again later. If the problem persists, please contact your system administrator.");
		return false;
	}
}

/**
 * Sends the GET to the server and returns the response.
 * @return The response root element as text from the http get. 
 * 		   May be null if failure has occured, or call is asyndchrounous.
 */
AJAX.prototype.doGet = function()
{
	if (this.m_bAddTimestamp)
	{
		this.addParm("now", (new Date()).getTime());
	}
	var strQS = this.m_strUrl;
	if ( this.m_params != "" )
	{
		strQS += strQS.indexOf("?") == -1 ? "?" : "";
    	strQS += strQS.indexOf("?") == strQS.length - 1 ? "" : "&";
    	strQS += this.m_params.charAt(0) == "&" ? this.m_params.substring(1) : this.m_params;
    }
	this.m_oHttp.open("GET", strQS, this.m_bAsync);
	this.m_oHttp.setRequestHeader("Accept-Charset", this.m_charset);
	//this.m_oHttp.setRequestHeader("Connection", "close");
	try
	{
		this.m_oHttp.send(null);
		if (!this.m_bAsync)
		{
			return this.handleHttpResponse();
		}
		return null;
	}
	catch (e)
	{
		alert("Unable to communicate with server. Please try again later. If the problem persists, please contact your system administrator.");
		return false;
	}
}

/**
 * Convenience method to handle synchronous calls
 */
AJAX.prototype.handleHttpResponse = function()
{
	if (this.m_oHttp.readyState == 4)
	{
		var strWarning = this.m_oHttp.getResponseHeader("Server-Warning");
		if (strWarning != null && strWarning != "")
		{
			// TODO: Add handle warning here
			this.m_lastWarningMessage = strWarning;
			this.m_lastErrorMessage = "Warning! Server returned: " + this.m_oHttp.status + " " + this.m_oHttp.statusText + " Warning text: " + strWarning;
			if (this.m_bStopOnWarning)
			{
				alert(this.m_lastErrorMessage);
				return false;
			}
		}
		if (this.m_oHttp.status != 200)
		{
			if (this.m_bDebug)
			{
				alert("Debug Err: " + this.m_oHttp.status + "\n" + this.m_oHttp.responseText);
			}
			this.m_lastErrorMessage = "Error! Server returned: " + this.m_oHttp.status + " " + this.m_oHttp.statusText;
			this.m_lastWarningMessage = this.m_lastErrorMessage;
			if (this.m_bStopOnError)
			{
				alert(this.m_lastErrorMessage);
				return false;
			}
		}
		if (this.m_fPostProcess)
		{
			if ( this.m_returnType == "text" )
			{
				return this.m_fPostProcess(this.m_oHttp.responseText == null ? null : this.m_oHttp.responseText);
			}
			return this.m_fPostProcess(this.m_oHttp.responseXML == null ? null : this.m_oHttp.responseXML.documentElement);
		}
		if ( this.m_returnType == "text" )
		{
			return this.m_oHttp.responseText;
		}
		return this.m_oHttp.responseXML;
	}
}

/**
 * Adds a parameter to the call.
 * @param strName parameter name
 * @param strValue parameter value
 */
AJAX.prototype.addParm = function(strName, strValue)
{
	var strNewParm = "&" + encodeURIComponent(strName) + "=";
	strNewParm += (typeof(strValue) == 'undefined' ?  strName : encodeURIComponent(strValue));
	this.m_params += strNewParm;
}

/**
 * Takes all values from specified form and adds them to the body or query string.
 * @param oForm (FORM) The form to read elements from.
 */
AJAX.prototype.handleForm = function(oForm)
{
	if (typeof(oForm) == 'string')
	{
		oForm = document.getElementById(oForm);
	}
	var arrElms = oForm.elements;
	var intElemCount = arrElms.length;
	for (var i=0; i < intElemCount; i++)
	{
		this.handleFormElm(arrElms.item(i));
	}
}

AJAX.prototype.handleFormElm = function(oElm)
{
	if (typeof(oElm) == 'string')
	{
		oElm = document.getElementById(oElm);
	}
	if (oElm.value != null && (oElm.checked || oElm.type != "radio"))
	{
		var strValue;
		if (oElm.type == "radio" || oElm.type == "checkbox")
		{
			if (oElm.checked)
			{
				strValue = (oElm.value ? oElm.value : "checked");
			}
			else
			{
				strValue = "";
			}
		}
		else
		{
			strValue = oElm.value;
		}
		if ( oElm.name && oElm.name != "" || oElm.id && oElm.id != "" )
		    this.addParm(oElm.name == "" ? oElm.id : oElm.name, strValue);
	}
}

/**
 * Sets the member variable to the desired return type.
 * Currently supported: text, xml (DOM)
 */
AJAX.prototype.setReturnType = function(strReturnType)
{
	this.m_returnType = strReturnType;
}

/**
 * Convenience function to be treated as private
 * @return a newly created XMLHttp object or null if object could not be created.
 */
function prepareXMLHttp()
{
	var oHttp = null;
	if (window.XMLHttpRequest)
	{ // IE 7, FireFox, Mozilla, Safari,...
	   oHttp = new XMLHttpRequest();
	   if (oHttp.overrideMimeType)
	   {
	      oHttp.overrideMimeType('text/xml');
	   }
	}
	else if (window.ActiveXObject)
	{ // IE 6
	   try
	   {
	      oHttp = new ActiveXObject("Msxml2.XMLHTTP");
	   }
	   catch (e)
	   { // IE 5
	      try
	      {
	         oHttp = new ActiveXObject("Microsoft.XMLHTTP");
	      }
	      catch (e)
	      {}
	   }
	}
	return oHttp;
}
