//
// The XmlHttp object - used for making XmlHttp requests
//
XmlHttp = new function()
{
	var isSupported = null;
	var ieObjectId  = null;

	//
	// Check if the browser supports XmlHttp
	//
	this.supported = function()
	{
		if (isSupported == null)
		{
			if (window.XMLHttpRequest)
				isSupported = true;
				
			else if (window.ActiveXObject && (getIEObjectId() != null))
				isSupported = true;
				
			else
				isSupported = false;
		}
		return isSupported;
	}

	//
	// Make an XmlHttpRequest
	//
	this.makeRequest = function(url, method, data, callback, context, usePost)
	{
		// Use the current url if we don't have one
		if (url == null)
			url = document.location.href.substring(0, document.location.href.length - document.location.hash.length);

		if ((typeof(usePost) == 'undefined') || (usePost == null))
			usePost = false;
			
		var request = createRequest(context);
		var async   = (typeof(callback) == 'function');
		
		if (async)
			request.obj.onreadystatechange = function()
				{
					if (request.obj.readyState == 4)
						callback(new XmlHttp.Response(request));
				}
		
		var postData = 'XmlHttpRequestMethod=' + method;
		
		// data should be an object of the form { argName: argvalue, hello: cheese }
		for (var argName in data)
			postData += '&' + argName + '=' + enc(data[argName]);
		
		if (usePost)
		{
			request.obj.open('POST', url, async);
			request.obj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
			request.obj.send(postData);
		}
		else
		{
			request.obj.open('GET', url + '?' + postData, async);
			request.obj.setRequestHeader('Content-Type', '');
			request.obj.send(null);
		}
		
		if (!async)
			return new XmlHttp.Response(request);
	}

	//
	// Stop all XmlHttpRequests
	//
	this.stopRequests = function()
	{
		if (XmlHttp.requests)
		{
			for (var i = 0; i < XmlHttp.requests.length; i++)
			{
				if ((XmlHttp.requests[i] != null) && (XmlHttp.requests[i].abort))
					XmlHttp.requests[i].abort();
			}
		}
	}

	//
	// Clean up any XmlHttpRequests on unload to make sure we don't hog any memory
	//
	this.cleanup = function(e)
	{
		if (XmlHttp.requests)
		{
			XmlHttp.stopRequests();
			
			XmlHttp.requests = null;
		}
	}

	//--------------------------------------------------------------------
	// Private methods
	//--------------------------------------------------------------------
	
	//
	// Create a new XmlHttpRequest
	//
	function createRequest(context)
	{
		if (!XmlHttp.requests)
		{
			XmlHttp.requests = [];
			EventManager.addEvent(window, 'unload', XmlHttp.cleanup);
		}
		
		for (var i = 0; i < XmlHttp.requests.length; i++)
		{
			if (XmlHttp.requests[i].obj.readyState == 4)
			{
				XmlHttp.requests[i].obj.onreadystatechange = function() { };
				XmlHttp.requests[i].obj.abort();
				XmlHttp.requests[i].context = context;	// RH changed this from null to context
				return XmlHttp.requests[i];
			}
		}

		var pos = XmlHttp.requests.length;

		XmlHttp.requests[pos] = {};
		XmlHttp.requests[pos].obj = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject(getIEObjectId());
		XmlHttp.requests[pos].context = context;
		
		return XmlHttp.requests[pos];
	}
	
	//
	// get the ID of the XmlHttpObject to use in IE
	//
	function getIEObjectId()
	{
		if (ieObjectId == null)
		{
			var ieObjects = ['MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP'];
			
			for (var i = 0; i < ieObjects.length; i++)
			{
				try
				{
					var r = new ActiveXObject(ieObjects[i]);
					ieObjectId = ieObjects[i];
					break;
				}
				catch (e) { }
			}
		}
		return ieObjectId;
	}
};

//
// The response object
//
XmlHttp.Response = function(request)
{
	this.request = request.obj;
	this.error = null;
	this.value = null;
	this.context = request.context;
	
	if (request.obj.status != 200)
		this.error = new XmlHttp.Error(request.obj.status, 'HTTP request failed with status: ' + request.obj.status);
	else
	{
		try
		{
			var response = {};

			if ((request.obj.responseText != null) && (request.obj.responseText.length > 0))
				response = eval('(' + request.obj.responseText + ')');	// I have no idea why the extra brackets are required here, but they are

			if (response.value != null)
				this.value = response.value;
				
			else if (response.error != null)
				this.error = response.error;
				
			else
				this.error = new XmlHttp.Error(0, 'No response');
		}
		catch (e)
		{
			this.error = new XmlHttp.Error(e.number, e.message);
		}
	}
};

//
// The error object
//
XmlHttp.Error = function(number, message)
{
	this.number  = number;
	this.message = message;
};