// copyright 2008 Damien Watson, damien.watson@gmail.com

function report(msg, el){

	if(!!el === false) el = 'feedback';
	try{
		xGetElementById(el).innerHTML += '<br>' + msg;
	}catch(e){
		alert(e + "\n\n" + msg);
	}
}

var xhr = {

	READY_STATE_UNINITIALIZED: 0,
	READY_STATE_LOADING: 1,
	READY_STATE_LOADED: 2,
	READY_STATE_INTERACTIVE: 3,
	READY_STATE_COMPLETE: 4,

	req: null,		// will store url
	silent: false,		// if true, don't update indicator
	indicator: null,	// shows status of request to user
	active: false,		// shows whether xhr is currently processing request
	debug: true,		// turn on console debugging

	request : function(url, method, params, silent, contentType){

		try{

			if(xhr.active == false){

				xhr.active = true;
				xhr.indicator = xGetElementById('connection');
				xhr.req = url;
				xhr.silent = silent ? silent : false;
				xhr.send(url, method, params, contentType);

			}else{
				xhr.indicator.innerHTML = 'Busy';
				report('busy');
			}

		}catch(e){
			xhr.defaultError(e);
		}
	},

	send : function(url, request_method, silent){

		var connection;
		if (window.XMLHttpRequest) { // Mozilla, Safari,...

			connection = new XMLHttpRequest();

		} else if (window.ActiveXObject) { // IE

			try{
				connection = new ActiveXObject("Msxml2.XMLHTTP");
			}catch(e){

				try{
					connection = new ActiveXObject("Microsoft.XMLHTTP");
				}catch(e){}
			}
		}

		if (connection) {
	
			try{
	
				connection.onreadystatechange = function(){
		
					if (connection.readyState == 1) {
						xhr.indicator.style.backgroundColor = '#FFFF33';
						xhr.indicator.innerHTML = 'Loading';
					}
					if (connection.readyState == 4) {
						if (connection.status == 200) {
							xhr.indicator.style.backgroundColor = '#33FF33';
							xhr.indicator.innerHTML = 'Ready';
							xhr.read(connection.responseText);
						}else{
							xhr.indicator.style.backgroundColor = '#FF3333';
							xhr.indicator.innerHTML = "<a href=\"" + xhr.req + "\">Retry</a>";
							xhr.defaultError('failed');
						}
					}
				}

				if(connection.overrideMimeType){
					connection.overrideMimeType("text/html; charset=ISO-8859-1");
				}

				connection.open(request_method, url, true);
				connection.send(null); // if post, put post vars here, apparently

			}catch(e){

				if(xhr.debug === true){
					msg = e + "<br>request data: "
						+ "<br> readyState:" + connection.readyState
						+ "<br> status: " + connection.status
						+ "<br> headers: " + connection.getAllResponseHeaders() + "<br>";
					xhr.defaultError(msg);
				}else{
					xhr.defaultError(e);
				}
			}

		}else{
			xhr.defaultError('Cannot create an XMLHTTP instance.');
			return false;
		}
	},

	defaultError : function(msg){
		xhr.active = false;
		report("Error sending request: " + msg);
	},

	read : function(xml){

		try{ //Internet Explorer

			xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async="false";
			xmlDoc.loadXML(xml);

		}catch(e){

			try{ //Firefox, Mozilla, Opera, etc.
				parser = new DOMParser();
				xmlDoc = parser.parseFromString(xml, "text/xml");
			}catch(e){
				xhr.defaultError(e);
			}
		}

		try{
			xhr.update(xmlDoc);
		}catch(e){
			xhr.defaultError(e);
		}
	},

	update : function(xmlDoc){

		report('updating');

		var x = xmlDoc.getElementsByTagName('element');
		for (var i = 0, len = x.length; i < len; i++){

			var command = {};

			for (var j = 0, nodes = x[i].childNodes.length; j < nodes; j++){
				var varname = x[i].childNodes[j].tagName;
				var varval = x[i].childNodes[j].firstChild.nodeValue;
				command[varname] = varval;
			}

			if(el = xGetElementById(command.node)){

				switch(command.mode){

					case 'replace':
						el.innerHTML = command.value;
					break;
					case 'prepend':
						el.innerHTML = command.value + el.innerHTML;
					break;
					case 'append':
						el.innerHTML = el.innerHTML + command.value;
					break;
					case 'clear':
						el.innerHTML = '';
					break;
					default:
						el.innerHTML = command.value;
					break;
				}

				if(xhr.debug === true){
					report(command.node + ': ' + command.value, 'debug');
				}

			}else{
				if(xhr.debug === true){
					report('Element not found, ' + command.node + ': ' + command.value, 'debug');
				}
			}

			if(!!command.callback){
				do_callback(command.callback);
			}
		}

		xhr.active = false;
	}
}