/**
 * AJAX Module v2.2
 * Copyright 2008-2009 Petro Salema
 * www.petrosalema.com
 */

var Ajax = {

	RETRY_DELAY: 1000, // Interval between retrying a busy request
	
	getTransport: function()
	{
		if (window.XMLHttpRequest)
			return new XMLHttpRequest();
		else if (window.ActiveXObject)
			return new ActiveXObject("Microsoft.XMLHTTP");
		else
			return false;
	},
	
	dispatch: function(request_id, request_type, postfields)
	{ // We pass a reference to the ajax request object rather than the object itself for frugality
	
		var r = Ajax.connections[Ajax.indexOf(request_id)].request;
		
		if (r.busy) { // If we are busy try again in 1 second
			setTimeout(Ajax.dispatch.bind({}, r), Ajax.RETRY_DELAY);
			return;
		}
		
		var call = r.url;
		if (r.fresh)
			call += ((r.url.indexOf('?') > -1) ? '&' : '?') + 'rand=' + Math.random();
		
		var t = r.transport;
		
		try
		{
			t.open(request_type, call, true);
			if (postfields)
				t.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			t.send(encodeURI(postfields));
			t.onreadystatechange = r.callback.bind(r);
		}
		catch(e)
		{
			r.failed("Could not send request");
			return;
		}
		
		r.busy = true;
	},
	
	remove: function(request_id)
	{ // Removes the Ajax request from the lists of connections

		var c = Ajax.connections;
		var i = Ajax.indexOf(request_id);
		var r = c[i];
		
		if (r) {
			clearTimeout(r.timer);
			r.timer = null;
			r.transport = null;
			r.request = null;
		}
		
		c.splice(i, 1);
	},
	
	indexOf: function(request_id)
	{
		var c = Ajax.connections;
		for(var i in c)
			if (c[i].id == request_id)
				return i;
	},
	
	connections: []
	
};

Ajax.Request = Class({

	// * * * * * * * * * * Ajax.Request Class * * * * * * * * * *
	
	transporter: null,
	busy:		 false,
	url:		 null,
	oncomplete:	 null,
	canvas:		 null,
	fresh:		 false,
	interval:	 false,
	timer:		 null,
	
	_initialize: function(url, oncomplete, postfields, fresh, interval)
	{
		this.id = (new Date).getTime();
		this.url = url;
		this.oncomplete = oncomplete;
		this.fresh = fresh || false;
		this.interval = interval || false;
		this.transport = Ajax.getTransport();
		
		var type = postfields ? "POST" : "GET";
		
		if (this.transport) {
			Ajax.connections.push({id:this.id, request:this});
			Ajax.dispatch(this.id, type, postfields);
		} else
			this.failed("Could not create HTTPRequest object");
	},
	
	callback: function()
	{
		var t = this.transport;
		
		if (t.readyState == 4) {
			try
			{
				if (t.status == 200)
					this.succeeded();
				else
					this.failed(t.status + " error!");
			}
			catch(e)
			{
				this.failed("Firefox error: " + e);
			}
		}
	},
	
	failed: function(msg)
	{
		if (!/Firefox error/.test(msg)) { /* Do nothing */ }
		this.transport.abort();
		Ajax.remove(this.id);
	},
	
	succeeded: function()
	{
		if (this.oncomplete)
			this.oncomplete(this.transport.responseText);

		if (this.interval) {
		// If it's a periodical request, then repeat it after interval milliseconds
			this.busy = false;
			this.timer = setTimeout(Ajax.dispatch.bind({}, this.id), this.interval);
		} else
			Ajax.remove(this.id);
	}

}); // * * * * * * * * * * / Ajax.Request Class * * * * * * * * * *