var ajax;


/* AJAX object adapted from http://www.hunlock.com/blogs/The_Ultimate_Ajax_Object */
function ajaxObject() {
	var that = this;
	this.updating = false;
	
	this.abort = function() {
		if (that.updating) {
			that.updating = false;
			that.AJAX.abort();
			that.AJAX = null;
		}
	}
	
	this.update = function(url, callbackFunction, passData, postMethod) { 
		if (that.updating) {
			return false;
		}
		that.AJAX = null;
		this.callback = callbackFunction || function () { };
		if (window.XMLHttpRequest) {
			// code for Firefox, Opera, IE7, etc.
			that.AJAX = new XMLHttpRequest();
		} else {
			// code for IE6, IE5
			try {
				that.AJAX = new ActiveXObject('MSXML2.XMLHTTP.3.0');
			} catch (e) {
				that.AJAX = new ActiveXObject("Microsoft.XMLHTTP");
			}
		}
		if (that.AJAX == null) {
			return false;
		} else {
			that.AJAX.onreadystatechange = function() {  
				if (that.AJAX.readyState == 4) {
					that.updating = false;
					that.callback(that.AJAX.responseText, that.AJAX.status, that.AJAX.responseXML);
					that.AJAX = null;
				}
			}
			that.updating = new Date();
			if (/post/i.test(postMethod)) {
				var uri = url + '?' + that.updating.getTime();
				that.AJAX.open("POST", uri, true);
				that.AJAX.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				that.AJAX.setRequestHeader("Content-Length", passData.length);
				that.AJAX.send(passData);
			} else {
				var uri = url + '?' + passData + '&timestamp=' + (that.updating.getTime());
				that.AJAX.open("GET", uri, true);
				that.AJAX.send(null);
			}
			return true;
		}
	}
}


/* AJAX handler object which maintains a pool of ajaxObjects to be used for concurrent communication
   Parameters: timeout in milliseconds and an ajax object limit
*/
function ajaxHandler(timeoutMS, maxObjects) {
	this.ajaxArray = [];

	this.timeoutMS = Math.max(timeoutMS, 100);
	this.maxObjects = Math.max(maxObjects, 1);
	
	this.query = function(url, callbackFunction, passData, postMethod) {
		var index = -1;
		var now = new Date();
		for (var i = 0; i <= this.ajaxArray.length && i < this.maxObjects; i++) {
			if (i == this.ajaxArray.length || this.ajaxArray[i] == null) {
				this.ajaxArray[i] = new ajaxObject();
				index = i;
				break;
			}
			if (this.ajaxArray[i].updating == false) {
				index = i;
				break;
			}
			// abort any requests that have passed beyond the timeout period
			if (this.ajaxArray[i].updating.getTime() + this.timeoutMS < now.getTime()) {
				this.ajaxArray[i].abort();
				index = i;
				break;
			}
		}
		this.active++;
		return this.ajaxArray[index].update(url, callbackFunction, passData, postMethod);
	}
}


// set up xmlhttp object
function getAjax() {
	if (ajax == null) {
		ajax = new ajaxHandler(2000, 5);
	}
	return ajax;
}
