var xmlhttp;
var activeRequests = new Object();
activeRequests.requests = new Array();
var cachedResponses = new Array();


function ActiveRequest()
{
  this.request = GetXMLHttpRequest();
  activeRequests.requests[this.index = activeRequests.requests.length] = this;
}

function GetXMLHttpRequest()
{
	var result;
	if (window.XMLHttpRequest) result = new XMLHttpRequest();
	else if (window.XMLHttpRequestProgID) result = new ActiveXObject(window.XMLHttpRequestProgID);
	else
	{
		var progIDs = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
		for (var i = 0; !result && i < progIDs.length; ++i)
		{
			var progID = progIDs[i];
			try
			{
				var x = new ActiveXObject(progID);
				window.XMLHttpRequestProgID = progID;
				result = x;
			}
			catch(e) { }
		}
	}
	return result;
}

function GetXMLHttpRequestResponse(x)
{
	var result = {'firstNodeValue': null, 'xml': null, 'text': null, 'object': null,'error': "BADRESPONSE"};
	if (x && x.status && x.status != 200) 
	{
		result.error = x.status + ': ' + x.statusText;
		if(x.responseText)
			result.text = x.responseText;
	}
	else if (x && x.responseText && x.responseText.length > 0)
	{	
		result.xml = x.responseXML;
		result.text = x.responseText;
		result.error = null;
		if(x.responseXML && x.responseXML.documentElement && x.responseXML.documentElement.hasChildNodes())
		{
			var doc = x.responseXML.documentElement;
			if((doc.childNodes[0] && doc.childNodes[0].hasChildNodes()) || (doc.childNodes[1] && doc.childNodes[1].hasChildNodes()))
			{
				if(doc.childNodes[0].firstChild)
					result.firstNodeValue = doc.childNodes[0].firstChild.nodeValue;
				else if (doc.childNodes[1] && doc.childNodes[1].firstChild) //Becuase Gecko thinks a \r is a node.
					result.firstNodeValue = doc.childNodes[1].firstChild.nodeValue;
				if(result.firstNodeValue)
				{
					if(result.firstNodeValue.indexOf('{') == 0)
					{
						result.object = new Array();
						for(n = 0; n < doc.childNodes.length; n++)
						{
							if(doc.childNodes[n] && doc.childNodes[n].firstChild 
								&& doc.childNodes[n].firstChild.nodeValue && doc.childNodes[n].firstChild.nodeValue.indexOf('{') == 0)
							{
								eval('result.object.push(' + doc.childNodes[n].firstChild.nodeValue + ');');
							}
						}
					}
					else
					{
						result.object = new Array();
						for(n = 0; n < doc.childNodes.length; n++)
						{
							if(doc.childNodes[n] && doc.childNodes[n].firstChild && doc.childNodes[n].firstChild.nodeValue)
								result.object.push(doc.childNodes[n].firstChild.nodeValue);
						}
					}
				}
			}
			else
			{
				result.firstNodeValue = doc.firstChild.nodeValue;
				if(result.firstNodeValue.indexOf('{') == 0)
					eval('result.object = ' + result.firstNodeValue);	
			}			
		}	
	}
	return result;
}

function MakeXMLHttpRequestCall(url, requestData, async, preRequestCallBack, preRequestCallBackArgs, callBack, callBackArgs)
{
	if(preRequestCallBack) preRequestCallBack(preRequestCallBackArgs);

	var fullRequestQuery = url + requestData;
	var result = null;
	if(!cachedResponses[fullRequestQuery])
	{
		var req = new ActiveRequest();
		if(req && req.request)
		{
			//In order to function correctly as an async call, there must be a call back method to handle the readystatechange
			var method = 'POST';
			if(typeof requestData == 'undefined' || requestData == null || requestData.length == 0)
				method = 'GET';
			req.request.open(method, url, (async && (typeof callBack == 'function')));
			req.request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
			if(callBack)
			{
				req.request.onreadystatechange = function()
				{
					if (req.request.readyState != 4) return;
					var result = GetXMLHttpRequestResponse(req.request);
					cachedResponses[fullRequestQuery] = result;
					if(callBackArgs) callBack(result, callBackArgs);
					else callBack(result);
					
					delete activeRequests.requests[req.request.index];
					delete req;
				}
			}
			
			req.request.send(requestData);
			
			if (!callBack)
			{
				result = GetXMLHttpRequestResponse(req.request);
				cachedResponses[fullRequestQuery] = result;
			}
			if (!async && $.browser.mozilla && callBack)
			{
				//Gecko browsers do not fire the onreadystatechange for Sync requests...
				cachedResponses[fullRequestQuery] = GetXMLHttpRequestResponse(req.request);
				if(callBackArgs)
					callBack(cachedResponses[fullRequestQuery], callBackArgs);
				else
					callBack(cachedResponses[fullRequestQuery]);
					
				delete activeRequests.requests[req.request.index];
				delete req;
			}
		}
	}
	else
	{
		if(!callBack) result = cachedResponses[fullRequestQuery];
		
		if(callBack && callBackArgs) callBack(cachedResponses[fullRequestQuery], callBackArgs);
		else if(callBack) callBack(cachedResponses[fullRequestQuery]);
	}
	return result;
}

function processXMLHttp(asyncTrueOrFalse,whenFinishedFunction,XMLHttpPageURL,stringToPassToProcessingPage,whileProcessingFunction)
{
//	alert('processXMLHttp is DEPRICATED - Please refactor to use MakeXMLHttpRequestCall');
  if(whileProcessingFunction){
    eval(whileProcessingFunction);
  }
  
  if(window.XMLHttpRequest){
    xmlhttp = new XMLHttpRequest();
	//HACK!! Fix this so that FF can be set to false
	asyncTrueOrFalse = true;
	}else if(window.ActiveXObject){
    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
	xmlhttp.onreadystatechange=whenFinishedFunction;
	xmlhttp.open("POST", XMLHttpPageURL, asyncTrueOrFalse);
	xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	xmlhttp.send(stringToPassToProcessingPage);
}

function LazyRef(id, instance)
{
	this.id = id;
	this.__instance = instance;
	this.instance = function()
	{
		if(!this.__instance && this.id)
		{
			var response = MakeXMLHttpRequestCall('/_webservices/ObjectSerializationRequests.asmx/GetObject', 'id=' + this.id, false, null, null, null, null);
			if(response && response.object)
				this.__instance = response.object;
			
			response = null;
		}
		return this.__instance;
	}	
}
