/**
 * AjaxClient
 * @author David G. Matarrodona
 */
function AjaxClient(sUrl,oDebugElement){
	this.client = null;
	this.url = sUrl!=undefined? sUrl : "";
	this.debug = oDebugElement;
	
	// Methods
	if(typeof AjaxClient._initialized == "undefined"){	
		/**
		 * Constructor
		 */
		AjaxClient.prototype.init = function(){		
			if(typeof XMLHttpRequest != "undefined" && window.addEventListener){
				this.client = new XMLHttpRequest();
				return;
			}
	
			var arrSignatures = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
			for(var i=0;i<arrSignatures.length;i++){
				try{
					var oRequest = new ActiveXObject(arrSignatures[i]);
					this.client = oRequest;
					return;
				}catch(oError){}
			}
			throw new Exception("MSXML not installed!");
		}
		
		/**
		 * Sends and receives objects
		 * @param string sAction
		 * @param Object oObject
		 * @param boolean bAsync
		 * @param function(Object,int,string) fHandler 
		 */
		AjaxClient.prototype.sendAndGetObject = function(sAction,oObject,bAsync,fHandler){
			var oClient = this.client;
			var oDebug = this.debug;
			
			oClient.open("post",this.url+"/"+sAction,bAsync);

			if(bAsync){
				oClient.onreadystatechange = function() { 
					if(oClient.readyState==4){
						if(oDebug) oDebug.innerHTML = oClient.responseText;

						if(oClient.status==200)
							fHandler(JSON.parse(oClient.responseText),oClient.status,oClient.statusText);
						else
							fHandler(null,oClient.status,oClient.statusText);
					}
				}
				oClient.send(JSON.stringify(oObject));
			}
			else{
				oClient.send(JSON.stringify(oObject));
				if(oDebug) oDebug.innerHTML = oClient.responseText;
				if(oClient.status==200)
					return JSON.parse(oClient.responseText);
				else
					throw oClient.status+" : "+oClient.statusText;
			}
		}
		
		/**
		 * Sends parameters and receives string
		 * @param string sAction
		 * @param Hashtable oParams
		 * @param boolean bAsync
		 * @param function(string,int,string) fHandler
		 */
		AjaxClient.prototype.sendParameters = function(sAction,oParams,bAsync,fHandler){
			var oClient = this.client;
			var oDebug = this.debug;
			
			oClient.open("post",this.url+"/"+sAction,bAsync);
			oClient.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
			
			var keys = oParams.keys();			
			var sParams = "";
			for(var i=0;i<keys.length;i++){
				sParams += encodeURIComponent(keys[i])+"="+encodeURIComponent(oParams.get(keys[i]));
				if(i<(keys.length-1))
					sParams += "&";
			}
			
			if(bAsync){
				oClient.onreadystatechange = function() { 
					if(oClient.readyState==4){
						if(oDebug) oDebug.innerHTML = oClient.responseText;

						if(oClient.status==200)
							fHandler(oClient.responseText,oClient.status,oClient.statusText);
						else
							fHandler(null,oClient.status,oClient.statusText);
					}
				}
				oClient.send(sParams);
			}
			else{
				oClient.send(sParams);
				if(oDebug) oDebug.innerHTML = oClient.responseText;
				if(oClient.status==200)
					return oClient.responseText;
				else
					throw oClient.status+" : "+oClient.statusText;
			}
		}

		/**
		 * Sends parameters and receives object
		 * @param string sAction
		 * @param Hashtable oParams
		 * @param boolean bAsync
		 * @param function(string,int,string) fHandler
		 */
		AjaxClient.prototype.getObject = function(sAction,oParams,bAsync,fHandler){
			var oClient = this.client;
			var oDebug = this.debug;

			oClient.open("post",this.url+"/"+sAction,bAsync);
			oClient.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

			var keys = oParams!=null? oParams.keys() : new Array();			
			var sParams = "";
			for(var i=0;i<keys.length;i++){
				sParams += encodeURIComponent(keys[i])+"="+encodeURIComponent(oParams.get(keys[i]));
				if(i<(keys.length-1))
					sParams += "&";
			}
			
			if(bAsync){
				oClient.onreadystatechange = function() { 
					if(oClient.readyState==4){
						if(oDebug) oDebug.innerHTML = oClient.responseText;
						if(oClient.status==200)
							fHandler(JSON.parse(oClient.responseText),oClient.status,oClient.statusText);
						else
							fHandler(null,oClient.status,oClient.statusText);
					}
				}
				oClient.send(sParams);
			}
			else{
				oClient.send(sParams);
				if(oDebug) oDebug.innerHTML = oClient.responseText;				
				if(oClient.status==200)
					return JSON.parse(oClient.responseText);
				else
					throw oClient.status+" : "+oClient.statusText;
			}
		}

		/**
		 * Sends an object and receive string
		 * @param string sAction
		 * @param Object oObject
		 * @param boolean bAsync
		 * @param function(Object,int,string) fHandler 
		 */
		AjaxClient.prototype.sendObject = function(sAction,oObject,bAsync,fHandler){
			var oClient = this.client;
			var oDebug = this.debug;

			oClient.open("post",this.url+"/"+sAction,bAsync);

			if(bAsync){
				oClient.onreadystatechange = function() { 
					if(oClient.readyState==4){
						if(oDebug) oDebug.innerHTML = oClient.responseText;
						if(oClient.status==200)
							fHandler(oClient.responseText,oClient.status,oClient.statusText);
						else
							fHandler(null,oClient.status,oClient.statusText);
					}
				}
				oClient.send(JSON.stringify(oObject));
			}
			else{
				oClient.send(JSON.stringify(oObject));
				if(oDebug) oDebug.innerHTML = oClient.responseText;
				if(oClient.status==200)
					return oClient.responseText;
				else
					throw oClient.status+" : "+oClient.statusText;
			}
		}

		/**
		 * Sends a form and receive string in "asynchronous" mode
		 * @param string sAction
		 * @param Object oForm
		 * @param function(string) fHandler 
		 */
		AjaxClient.prototype.sendForm = function(sAction,oForm,idFrame,fHandler){
			var oClient = this.client;
			var oDebug = this.debug;

			var oFrame = document.getElementById(idFrame);
			
			if(oFrame.name.trim()=="")
				oFrame.name = oFrame.id;
			
			oForm.target = oFrame.name;
			oForm.action = "/"+sAction;
			if(oFrame.addEventListener){
				oFrame.onload = function(){
					fHandler(oFrame.contentWindow.document.body.innerHTML);
				}
			}
			else {
				oFrame.onreadystatechange = function(){
					try{
						if(oFrame.contentWindow.document.readyState=="complete")
							fHandler(oFrame.contentWindow.document.body.innerHTML);
					}catch(ex){
						oFrame.onreadystatechange = null;
						fHandler(ex);
					}
				}
			}
			
			oForm.submit();			
		}
		
		AjaxClient._initialized = true;		
	}
	
	this.init();
}

