///compress=false
/*
	Copyright (C) 2005 Ekina Ltd. All Rights Reserved.
		
	Contains objects and methods to handle cross browser asyncronous data postback and reply.
	
	Usage:
		
		JSPBHandler class
		
			JSPBHandler.invoke(methodInfo, callback, sender)
		
			methodInfo:		An instance of a JSPBMethodInfo class describing the method to invoke on the server.
			callback:		A function pointer to call.
			sender:			(Optional) An object to pass to the callback method.
			
			When the callback method is called, the following arguments are passed:
			
			sender:			The object defined in the invoke method.
			ret:			The returned object from the server.
		
		JSPBMethodInfo class
		
			JSPBMethodInfo(methodName, className, assemblyName)
			
			methodName:		The name of the method to invoke.
			className:		The name of the class the method resides.
			assemblyName:	The name of the assembly in which the class resides.
			
			JSPBMethodInfo.addArgument(data, type, assembly)
			
			data:			The data to pass.
			type:			A string representation of the data type.
			assembly:		(Optional) The assembly the data type is defined if custom.
		
	
	Example:
		
		//This method will be called by JSPB upon server reply
		function getPersonCallback(sender, ret) {
			alert(sender);
			//Alerts "hello world"
			
			alert(ret.Name);
			//Alerts the name of the person
		}
		
		function getPerson(id) {
			var mi = JSPBMethodInfo("GetPersonByID", "Ekina.People.Person", "Ekina.people");
			mi.addArgument(id, "int");
			JSPBHandler.invoke(mi, getPersonCallback, "hello world")
		}
*/
function JSPBHandler(){};
JSPBHandler.defaultInvokeUrl = window.location.href;
JSPBHandler.invokeNoReturn = function(methodInfo){JSPBHandler.invoke(methodInfo, null);};
JSPBHandler.invoke = function(methodInfo, callback, sender){var invoker = JSPBHandler._createInvoker(callback, sender);JSPBHandler._invoke(invoker, methodInfo);return invoker;};
JSPBHandler._invoke = function(invoker, methodInfo){invoker.invoke(methodInfo);};
JSPBHandler._createInvoker = function(callback, sender){return new JSPBInvoker(callback, sender);};
JSPBHandler.createHttpObject = function(){var xmlhttp = false;try{xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");}catch(ex1){try{xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");}catch(ex2){xmlhttp = false;}}if(!xmlhttp && typeof XMLHttpRequest!='undefined')xmlhttp = new XMLHttpRequest();return xmlhttp;};

function JSPBHelper(){}

JSPBHelper.parseBool = function(value){
	if(value == null) return false;
	return value.toString() == "true";
}

function JSPBInvoker(callback, sender){
	this.callback = callback;
	this.xmlhttp = JSPBHandler.createHttpObject();
	this.timer = null;
	this.sender = sender;
	this.cancel = false;
}

JSPBInvoker.prototype.invoke = function(methodInfo){
	var jspb = methodInfo.serialize();
    this.async = true;
    if(this.async){
        this._invokeAsyncServerMethod(jspb);
    }
    else{
        this._invokeServerMethod(jspb);
	    this._invokeCallback();
	}
}

JSPBInvoker.prototype._invokeCallback = function(){
    if (this.cancel) return;
	var ret = this.xmlhttp.responseText;

	if(ret.substring(0, "ex=".length) == "ex="){
		ret = ret.substring(3);
		alert(ret);
	}
	else{

		var retobj;
		if(ret.contains('session has timed out'))
		{
			alert("Your session has timed out, returning you to the login screen");
			location.reload();
			return;
		}
		if(this.callback){
			eval("retobj = " + ret);
			this.callback(this.sender, retobj);
		}
	}
}

JSPBInvoker.prototype._invokeServerMethod = function(methodInfoXml){

	this.xmlhttp.open("POST", window.location, false);
	this.xmlhttp.send(methodInfoXml);
}

JSPBInvoker.objs = new Array();

JSPBInvoker.prototype._invokeAsyncServerMethod = function(methodInfoXml){

    var index = JSPBInvoker.objs.length;
    JSPBInvoker.objs[index] = this;
    this.xmlhttp.open("POST", window.location, true);
	this.xmlhttp.send(methodInfoXml);
	if(JSPBInvoker.objs[index].checkState)
		this.timer = window.setInterval("new function(){JSPBInvoker.objs[" + index + "].checkState(" + index + ");}", 100);
}

JSPBInvoker.prototype.checkState = function(index){
	
    if(this.xmlhttp.readyState==4){    
        window.clearInterval(this.timer);
        JSPBInvoker.objs[index] = null;
        this._invokeCallback();
    }
}

function JSPBMethodInfo(methodName, className, assemblyName){
	this.methodName = methodName;
	this.assemblyName = assemblyName == null ? "" : assemblyName;
	this.className = className;
	this.args = new Array();
}

JSPBMethodInfo.prototype.addArgument = function(data, type, assembly){
	this.args[this.args.length] = new JSPBMethodArgument(data, type, assembly);
}

JSPBMethodInfo.prototype.serialize = function(){
	var retXml = "";
	retXml += "<jspb_invoke>";
	retXml += "<method>" + this.methodName + "</method>";
	retXml += "<class>" + this.className + "</class>";
	retXml += "<assembly>" + this.assemblyName + "</assembly>";
	retXml += "<args>";
	for(var i = 0; i < this.args.length; i++){
		retXml += "<arg type=\"" + this.args[i].type + "\" assembly=\"" + this.args[i].assembly + "\"><![CDATA[" + this.args[i].data + "]]></arg>";
	}
	retXml += "</args>";
	retXml += "</jspb_invoke>";
	return retXml;
}

function JSPBMethodArgument(data, type, assembly){
	this.data = data;
	if(type == null)
		type = typeof(data);
	this.type = type;
	this.assembly = assembly ? assembly : "";
}