/**
 * SOE Platform - Remote Procedure Call Object
 * @class rpc
 * @requires debug.js, browser.js
 * @author Scott Clarke, Sean White
 * @constructor none
 */
var rpc = {
	
	/**
	 *  RPC Object Properties
	 */
	async: true,
	httpResponseText: null,
	showRPCStatus: false,
	responseHandler: null,
	currentState: "Connection Uninitialized.",
	connState: ["Connection Uninitialized.","Connection Open. Wait for Request.","Data recieved.","Processing Data.","Request Complete","Unknown RPC state."],
	version : 0.9,
	statusIcon : "<div align='center' style='padding: 10px;'><img src='/images/ajax-loader.gif' align='absmiddle' alt='Loading'/><div id='percentLoaded'></div></div>",
	preventCaching : true,
	
	
	/**	
	 * The <tt>doHttpRequest</tt> handles making remote http requests and sending the 
	 * results to a div in the page.
	 * Example:
	 * 	rpcLib.doHttpRequest('index.html','?param=1&param=2','targetLayerID'); 
	 * @param (String) URL to fetch 
	 * @param (String) query string for rcp call. include starting '?'
	 * @param (String) target Div to inject content into. 
	 * 			(Optional) set targetLayer as 'javascript' - just blindly execute the response as 100% pure JS.
	 * 			(Optional) set targetLayer as 'nothing' - send response as like a post for things such as logging.
	*/
	doHttpRequest : function (url, parameters, targetLayer) {
		var requestHandler = null;
		var http_request = rpc.createRequestObject();
		if(targetLayer !== null) {
			if(targetLayer == "variable") {
				requestHandler = function() { rpc.sendResultsToVariable(http_request); };
			} else if(targetLayer == "javascript") {
				requestHandler = function() { rpc.sendResultsToJavascript(http_request); };
			} else if(targetLayer == "nothing") {
				requestHandler = function() { rpc.sendResultsToNothing(http_request); };
			} else {
				requestHandler = function() { rpc.sendResultsToLayer(http_request, targetLayer); };
			}
		} else {
			requestHandler = function() { rpc.sendResultsToNothing(http_request); };
		}
		if(rpc.preventCaching) {
			currentDate = new Date();
			appendVal = currentDate.getUTCDay() + '' + currentDate.getUTCHours() + '' + currentDate.getUTCMonth() + '' + currentDate.getUTCMinutes() + '' +currentDate.getUTCSeconds() + '' + currentDate.getUTCMilliseconds();
			if(parameters.length != 0 || (url.indexOf('?') >= 0 || parameters.indexOf('?') >= 0)) {
				parameters = parameters + '&xtsx=' + appendVal;
			} else {
				parameters = '?xtsx=' + appendVal;
			}
		}
		//debug.append('HttpReq = ' + url + parameters);
		http_request.onreadystatechange = requestHandler;
		http_request.open('GET', url + parameters, rpc.async);
		http_request.send(null);
	},
	
	/**	
	 * The <tt>doHttpPost</tt> handles making remote http POST and sending the 
	 * results to a div in the page.
	 * Example:
	 * 	rpcLib.doHttpPost('index.html','?param=1&param=2','targetLayerID'); 
	 * @param (String) URL to fetch 
	 * @param (String) query string for rcp call. include starting '?'
	 * @param (String) target Div to inject content into. 
	 * 			(Optional) set targetLayer as 'javascript' - just blindly execute the response as 100% pure JS.
	 * 			(Optional) set targetLayer as 'nothing' - send response as like a post for things such as logging.
	*/
	doHttpPost : function (url, parameters, targetLayer) {
		var requestHandler = null;
		var http_request = rpc.createRequestObject();
		if(targetLayer !== null) {
			if(targetLayer == "variable") {
				requestHandler = function() { rpc.sendResultsToVariable(http_request); };
			} else if(targetLayer == "javascript") {
				requestHandler = function() { rpc.sendResultsToJavascript(http_request); };
			} else if(targetLayer == "nothing") {
				requestHandler = function() { rpc.sendResultsToNothing(http_request); };
			} else {
				requestHandler = function() { rpc.sendResultsToLayer(http_request, targetLayer); };
			}
		} else {
			requestHandler = function() { rpc.sendResultsToNothing(http_request); };
		}
		http_request.onreadystatechange = requestHandler;
		http_request.open('POST', url, rpc.async);
		http_request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
		http_request.send(parameters);		
	},	
	
	/**	
	 * The <tt>doHttpFunction</tt> handles making remote http requests and
	 * then send the results to a user defined request handler function. 
	 * This assumes that the response will be 100% pure JS with no HTML or anything.
	 * Example:
	 * 	function doSomethingWith(response) {
	 * 		//do something with the response here
	 * 	}
	 * 	var targetFunction = function (response) { doSomethingWith(reponse) }
	 * 	rpcLib.doHttpFunction('index.html','?param=1&param=2',targetFunction); 
	 * @param (String) URL to fetch 
	 * @param (String) query string for rcp call. include starting '?'
	 * @param (String) target Div to inject content into. 
	 * 			(Optional) set targetLayer to 'nothing' to send response as like a post such as logging.
	*/
	doHttpFunction: function (url, parameters, targetFunction) {
		var requestHandler = null;
		var http_request = rpc.createRequestObject();
		requestHandler = function() { rpc.sendResultsToFunction(http_request,targetFunction); };
		if(rpc.preventCaching) {
			currentDate = new Date();
			appendVal = currentDate.getUTCDay() + '' + currentDate.getUTCHours() + '' + currentDate.getUTCMonth() + '' + currentDate.getUTCMinutes() + '' +currentDate.getUTCSeconds() + '' + currentDate.getUTCMilliseconds();
			
			if(parameters.length != 0 || (url.indexOf('?') >= 0 || parameters.indexOf('?') >= 0)) {
				parameters = parameters + '&xtsx=' + appendVal;
			} else {
				parameters = '?xtsx=' + appendVal;
			}
		} 
		//debug.append('HttpReq = ' + url + parameters);
		http_request.onreadystatechange = requestHandler;
		http_request.open('GET', url + parameters, rpc.async);
		http_request.send(null);
	},

	/**	
	 * The <tt>doHttpPostFunction</tt> like doHttpPost, but sends results to custom function. 
	 * This assumes that the response will be 100% pure JS with no HTML or anything.
	 * Example:
	 * 	function doSomethingWith(response) {
	 * 		//do something with the response here
	 * 	}
	 * 	var targetFunction = function (response) { doSomethingWith(reponse) }
	 * 	rpcLib.doHttpPostFunction('index.html','?param=1&param=2',targetFunction); 
	 * @param (String) URL to fetch 
	 * @param (String) query string for rcp call. include starting '?'
	 * @param (String) target Div to inject content into. 
	 * 			(Optional) set targetLayer to 'nothing' to send response as like a post such as logging.
	*/
	doHttpPostFunction: function (url, parameters, targetFunction) {
		var requestHandler = null;
		var http_request = rpc.createRequestObject();
		requestHandler = function() { rpc.sendResultsToFunction(http_request,targetFunction); };
		http_request.onreadystatechange = requestHandler;
		http_request.open('POST', url, rpc.async);
		http_request.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
		http_request.send(parameters);		
	},
	
	/**
	 * The <tt>doHttpFunction</tt> returns a XML object populated with 
	 * xml from the requesting url. Assumes the response will be valid xml.
	 * @param (String) URL to fetch 
	 * @param (String) query string for rcp call. include starting '?'
	 * @param (String) target Div to inject content into.
	 * @return (XMLObject) xml object of response 
	 */
	doXmlFunction: function (url, parameters, targetFunction) {
		////debug.append("xml url=" + url + parameters);
		var xmlDoc = false;
		if (document.implementation && document.implementation.createDocument)
		{
			xmlDoc = document.implementation.createDocument("", "", null);
			xmlDoc.onload = targetFunction;
		}
		else if (window.ActiveXObject)
		{
			xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.onreadystatechange = function () {
				if (xmlDoc.readyState == 4) { targetFunction(xmlDoc); }
			};
	 	}
		else
		{
			//debug.append('Your browser can\'t handle this script');
			xmlDoc = false;
		}
		xmlDoc.load(url + parameters);
		////debug.append(xmlDoc);
		return xmlDoc;
	},
	
	/**
	 * function to handle making a new http request ojbect
	 */
	createRequestObject : function() {
		var http_request = false;
		if (window.XMLHttpRequest) { // Mozilla, Safari,...
			http_request = new XMLHttpRequest();
			if (http_request.overrideMimeType) {
				http_request.overrideMimeType('text/xml');
			}
		} else if (window.ActiveXObject) { // IE
			try {
				http_request = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
			try {
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
				http_request = false;
			}
		}
		if (!http_request) {
			////debug.append('Cannot create XMLHTTP instance');
			http_request = false;
		}	
		return http_request;
	},

	/**
	 * inject http request results to dom object - do not call directly
	 */
	sendResultsToLayer : function(http_request, targetLayer) { 
	
		state = http_request.readyState;
		var response = [{statusCode:0,contentText:''}];
		if(state <= 4) {
			switch(state) {
				case 0 :
					currState = rpc.connState[0];
					//debug.setStatusText(rpc.connState[0]);
					break;
				case 1 :
					currState = rpc.connState[1];
					document.getElementById(targetLayer).innerHTML = rpc.statusIcon;
					document.getElementById("percentLoaded").innerHTML = "25%";
					//debug.setStatusText(rpc.connState[1]);
					break;
				case 2 :
					document.getElementById("percentLoaded").innerHTML = "50%";
					currState = rpc.connState[2];
					////debug.setStatusText((http_request.status) + ' - ' + rpc.connState[2]);
					break;
				case 3 :
					document.getElementById("percentLoaded").innerHTML = "75%";
					currState = rpc.connState[3];
					//response.statusCode = http_request.status;
					////debug.setStatusText((http_request.status) + ' - ' + rpc.connState[3]);
					break;
				case 4 :
					//send html to browser dom element
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[4]);
					document.getElementById("percentLoaded").innerHTML = "100%";
					response.contentText = http_request.responseText;

					switch(http_request.status) {
						case 404:
							document.getElementById(targetLayer).innerHTML = "Page not found";
							break;
							
						case 503:
							document.getElementById(targetLayer).innerHTML = "There was a server error. Please try again later.";
							break;
						case 200:
							//send html to browser dom element
							currState = http_request.responseText;
							document.getElementById(targetLayer).innerHTML = currState;
							//find any script tags and execute thier content
							tempElem = document.createElement('temp');
							tempElem.innerHTML = http_request.responseText;
							scriptBlocksArray = tempElem.getElementsByTagName('script');
							break;
					}

					
					// loop over script tag block
					for(x=0; x < scriptBlocksArray.length; x++) {
						currBlock = scriptBlocksArray[x];
						eval(currBlock.innerHTML);
					}
					break;
				default :
					currState = rpc.connState[5];
					break;
			}
			//document.getElementById(targetLayer).innerHTML = currState;
		}
		
	
	},
	
	/**
	 * execute http request as pure javascript - do not call directly
	 */
	sendResultsToJavascript : function(http_request) { 
		//debug.append("sendResultsToJavascript");
		var state = http_request.readyState;
		var response = [{statusCode:0,contentText:''}];
		if(state <= 4) {
			switch(state) {
				case 0 :
					currState = rpc.connState[0];
					//debug.setStatusText(rpc.connState[0]);
					break;
				case 1 :
					currState = rpc.connState[1];
					//debug.setStatusText(rpc.connState[1]);
					break;
				case 2 :
					currState = rpc.connState[2];
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[2]);
					break;
				case 3 :
					currState = rpc.connState[3];
					////debug.setStatusText((http_request.status) + ' - ' + rpc.connState[3]);
					break;
				case 4 :
					//send html to browser dom element
					switch(http_request.status) {
						case 404:
							alert("Page not found");
							break;
							
						case 503:
							alert("There was a server error. Please try again later.");
							break;
						case 200:
							//send html to browser dom element
							eval(http_request.responseText);
							break;
					}
					//return true;
					break;
				default :
					currState = rpc.connState[5];
					break;
			}
			//debug.append(currState);
		}
	},		
	
	/**
	 * execute http request as pure javascript - do not call directly
	 */
	sendResultsToNothing : function(http_request) { 
		var state = http_request.readyState;
		if(state <= 4) {
			switch(state) {
				case 0 :
					currState = rpc.connState[0];
					//debug.setStatusText(rpc.connState[0]);
					break;
				case 1 :
					currState = rpc.connState[1];
					//debug.setStatusText(rpc.connState[1]);
					break;
				case 2 :
					currState = rpc.connState[2];
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[2]);
					break;
				case 3 :
					currState = rpc.connState[3];
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[3]);
					break;
				case 4 :
					//send html to browser dom element
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[4]);
					break;
				default :
					currState = rpc.connState[5];
					break;
			}
		}
	},		

	/**
	 * should return results back to a javascript variable, but doesnt work yet - do not call
	 */
	sendResultsToVariable : function(http_request) { 
		var state = http_request.readyState;
		var response = [{statusCode:0,contentText:''}];
		if(state <= 4) {
			switch(state) {
				case 0 :
					currState = rpc.connState[0];
					//debug.setStatusText(rpc.connState[0]);
					break;
				case 1 :
					currState = rpc.connState[1];
					//debug.setStatusText(rpc.connState[1]);
					break;
				case 2 :
					currState = rpc.connState[2];
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[2]);
					break;
				case 3 :
					currState = rpc.connState[3];
					response.statusCode = http_request.status;
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[3]);
					break;
				case 4 :
					//send html to browser dom element
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[4]);
					response.statusCode = http_request.status;
					response.contentText = http_request.responseText;
					break;
				default :
					currState = rpc.connState[5];
					break;
			}
		}
		if(state == 4) {
			return response;
		}
	},	
	
	/**
	 * return http results to a variable in JS - do no call directly
	 */  
	sendResultsToFunction : function(http_request, targetFunction) { 
		var state = http_request.readyState;
		var response = [{statusCode:0,contentText:''}];
		if(state <= 4) {
			switch(state) {
				case 0 :
					currState = rpc.connState[0];
					//debug.setStatusText(rpc.connState[0]);
					break;
				case 1 :
					currState = rpc.connState[1];
					//debug.setStatusText(rpc.connState[1]);
					break;
				case 2 :
					currState = rpc.connState[2];
					//debug.setStatusText(rpc.connState[2]);
					break;
				case 3 :
					currState = rpc.connState[3];
					//debug.setStatusText(rpc.connState[3]);
					break;
				case 4 :
					//send html to browser dom element
					//debug.setStatusText((http_request.status) + ' - ' + rpc.connState[4]);
					response.statusCode = http_request.status;
					response.contentText = http_request.responseText;
					targetFunction(response);
					break;
				default :
					////debug.setStatusText(http_request.status + ' - ' + rpc.connState[5]);
					currState = rpc.connState[5];
					break;
			}
		}
	},
	
	preloadImage : function (imageUrl, imageWidth, imageHeight) {
		var tempImage = new Image();
		tempImage.src = imageUrl;
		tempImage.height = imageHeight;
		tempImage.width = imageWidth;
		return tempImage;
	}	

};