// Make URLencoded POST or GET requests. Unpacks the result as JSON.
// To use this, create a ServerRequest.
// Set the property "method" (to either GET or POST)
// Set the property "command"
// Set the property "parameters" - assoc. array
// set the handler onloaded - this will be called with the JSON unpacked
// as its parameter.
// .onerror can also be set 
// Then call the send() method.
function ServerRequest() {
	this.request = XmlHttpFactory();
	this.baseUrl = window.location.href;
	this.baseUrl = this.baseUrl.substr(0,this.baseUrl.indexOf("/"));
	this.postUrl = this.baseUrl + "/events/gateway.php";
	this.loading = false;
	this.topNode = false;
	this.onloaded = false;
	this.parameters = new Object();
	this.command = false;
	this.onerror = HandleServerError;
	var me = this; // So we can access the object in callback methods.
	
	this.send = function() {
		if (this.loading) {
			// Should not happen.
			return;
		}
		
		this.loading = true;
		var payload = '';
		
		// Create form-encoded post.
		for (var key in this.parameters) {
			var value = this.parameters[key];
			payload = payload + key + "=" + this.escapeForPost(value) + "&";
		}
		var method = this.method.toUpperCase();
		// Send the command in the Path Info part
		var url = this.postUrl + "/" + this.command;
		if (method == 'GET') {
			url = url + "?" + payload;
		}
		this.request.open(method, url, true);
		this.request.onreadystatechange = this.readyStateChange;
		if (method == 'GET') {
			// Send it empty.
			this.request.send(null);
		} else {
			// Do a post.
			this.request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			this.request.send(payload);
		}
	}
	
	this.readyStateChange = function() {
		if ((me.request.readyState == 4) && (me.loading)) {
			me.loaded();
		}
	}
	
	this.loaded = function() {
		this.loading = false;
		// Do Something with the response.
		var txt = this.request.responseText;
		if (txt == '') {
			// This shouldn't happen, but may occasionally.
			// Ignore for the time being.
			return;
		}
		try {
			var response = eval(" junk = " + txt); // Unpack JSON.
		} catch (e) {
			// Failed to eval it. Invalid JSON.
			if (txt.length > 300) {
				txt = txt.substring(0,300);
			}
			HandleServerError("Invalid JSON response: " + txt +
				"\n Error: " + e.message);
			return;
		}
		// If it was an error, call onerror,
		// Otherwise call onloaded.
		var isError = false;
		var errmsg = 'unknown';
		if (response.error) {
			isError = true;
			errmsg = response.error;
		}
		
		if (isError) {
			if (this.onerror) {
				this.onerror(response);
			}
		} else {
			if (this.onloaded) {
				this.onloaded(response);
			}
		}
	}
	
	this.escapeForPost = function(str) {
		str = encodeURIComponent(str);
		str = str.replace(/\+/g, '%2b');
		return str;
	}
}

function XmlHttpFactory()
{
	/*
	 * For IE we use new ActiveXObject, except
	 * NOTE: Some versions of IE (7+) support native XMLHttpRequest and
	 * ActiveXObject. In those cases, we should use the former as
	 * it is more likely to bypass activex security.
	 *
	 * All non-IE browsers should work with XMLHttpRequest
	 */
	var request;
	if (window.XMLHttpRequest) {
		request = new XMLHttpRequest();
	} else {
		try {
			request = new ActiveXObject("Microsoft.XMLHTTP");
		} catch (e)
		{
			// Do something funky here.
			throw "XMLHttpRequest cannot be created";
		}
	}
	return request;
}

function HandleServerError(response)
{
	var errText;
	if (response.error) {
		errText = response.error;
	} else {
		// If it's a Javascript Error object..
		if (response.message) {
			errText = response.message;
		} else {
			errText = String(response);
		}
	}
	// Do something visible and obvious
	var errContainer = document.getElementById("servererror");
	if (! errContainer) {
		// Should do smething more sensible here.
		alert(errText);
		return;
	}
	errContainer.style.display = "block";
	document.getElementById("servererrormsg").innerHTML =
		HtmlEscape(errText);
}

