var meAjax = function()
{
	this.xmlhttp = null;
	this.reset();
	
	this.instanceHandle = meAjax.nextHandle;
	meAjax.nextHandle++;
	meAjax.instances[this.instanceHandle] = this;
}

meAjax.nextHandle = 1;
meAjax.instances = {};


/**
 * Release all ajax objects
 */
meAjax.releaseAll = function()
{
	for(var obj in meAjax.instances)
		meAjax.release(obj);
}


/**
 * Release given instance
 */
meAjax.release = function(handle)
{
	meAjax.instances[handle].abort();
	delete meAjax.instances[handle];
}


/**
 * Reset XMLHTTP object
 */
meAjax.prototype.reset = function()
{
	var tmp;
	
	this.abort();
	
	try {
		tmp = new XMLHttpRequest();
	} catch(e) {
		try {
			tmp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				tmp = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e) {
				tmp = null;
			}
		}
	}
	
	this.xmlhttp = tmp;
}


/**
 * Returns true if http request object is available
 */
meAjax.prototype.isAvailable = function()
{
	return this.xmlhttp !== null ? true : false;
}


/**
 * Set callback that is called on complete.
 * Callback function gets this Ajax instance as a parameter
 */
meAjax.prototype.setOnCompleteCallback = function(context, mtd)
{
	var obj = this, dispatch = this.dispatcher;
	
	this.xmlhttp.onreadystatechange = function()
	{
		return dispatch.call(obj, context, mtd);
	}
}


/**
 * Calls user defined callback on successful server response
 */
meAjax.prototype.dispatcher = function(context, mtd)
{
	if(this.xmlhttp.readyState != 4)
		return;
	
	//FF fix for occasionally throwing an exception here
	try {
		if(this.xmlhttp.status != 200)
			return;
	} catch(e) {
		return;
	}
	
	mtd.call(context, this);
}


/**
 * Create GET request
 */
meAjax.prototype.requestGet = function(url, getargs, async)
{
	url += this.formatArgs(getargs, true);
	
	if(async == undefined || async !== true)
		var async = false;
	
	this.xmlhttp.open("GET", url, async);
	this.xmlhttp.send(null);
	
	if(async)
		return true;
	
	if(this.xmlhttp.status != 200)
		return false;
	
	return true;
}


/**
 * Create POST request
 */
meAjax.prototype.requestPost = function(url, getargs, postargs, async)
{
	var post = "";
	
	url += this.formatArgs(getargs, true);
	post = this.formatArgs(postargs, false);
	
	if(async == undefined || async !== true)
		var async = false;
	
	this.xmlhttp.open("POST", url, async);
	this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	this.xmlhttp.setRequestHeader("Content-Length", post.length);
	this.xmlhttp.setRequestHeader("Connection", "close");
	this.xmlhttp.send(post);
	
	if(async)
		return true;
	
	if(this.xmlhttp.status != 200)
		return false;
	
	return true;
}


/**
 * Abort pending request
 */
meAjax.prototype.abort = function()
{
	if(this.xmlhttp !== null)
		this.xmlhttp.abort();
}


/**
 * Get server response as a raw text
 */
meAjax.prototype.getResponseText = function()
{
	if(this.xmlhttp.readyState != 4)
		return null;
	
	return this.xmlhttp.responseText;
}


/**
 * Get server response as an XML
 */
meAjax.prototype.getResponseXML = function()
{
	if(this.xmlhttp.readyState != 4)
		return null;
	
	return this.xmlhttp.responseXML;
}


/**
 * Format object of {key : value} pairs to request string
 * If getmode is true, add ? character in front
 */
meAjax.prototype.formatArgs = function(args, getmode)
{
	var i = 0, ret = "", val;
	
	if(args == undefined || args == null)
		return ret;
	
	for(key in args)
	{
		if(i++) ret += "&";
		
		if(args[key] === undefined || args[key] === null) val = "";
		else if(typeof args[key] == "boolean") val = (args[key] === true ? "true" : "false");
		else if(typeof args[key] == "object")
		{
			ret += this.objectToRequest(key, args[key]);
			continue;
		}
		else val = encodeURIComponent(args[key]);
		
		ret += encodeURIComponent(key) + "=" + val;
	}
	
	if((getmode != undefined && getmode == true) && ret.length > 0)
		ret = "?" + ret;
	
	return ret;
}


/**
 * Converts a javascript objects fields into an array suitable for request
 */
meAjax.prototype.objectToRequest = function(name, obj)
{
	var str = '', i = 0;
	
	if(obj == null)
		return str;
	
	for(var k in obj)
	{
		if(i++) str += '&';
		str += name + '[' + encodeURIComponent(k) + ']=' + encodeURIComponent(obj[k]);
	}
	
	return str;
}
