
function webServiceMethod(name, parent) {
	this.args = new Array();
	this.name = name;
	this.parent = parent;
	this.invoke = wsc_invokeMethod;
}

function webServiceClient(url, name) {
	this.asckt = new ajax('asckt');
	this.asckt.asyncronous = false;
	this.url = url;
	this.name = name ? name: 'wsclient';
	this.methods = new Array();
	
	this.init = function() {
		this.methods = wsc_getMethods(this, this.asckt.getXml(this.url + '?WSDL'));
	
		for (var i = 0; i < this.methods.length; i++) {
			var mname = this.methods[i].name;
			var wsname = this.name;
			eval('function fn_'+wsname+'_'+mname+'(){return wsc_invokeMethod(\''+wsname+'\', \''+mname+'\', arguments)}');
			this[this.methods[i].name] = eval('fn_'+wsname+'_'+mname);
		}
	}
	
	this.invoke = function(name, args) {
		
		
		var m = null;
		// ottengo il metodo corretto
		for (var i = 0; i < this.methods.length; i++) {
			if (this.methods[i].name == name) {
				m = this.methods[i];
				break;
			}
		}
		
		// controllo se i metodi corrispondono
		if (m.args.length == args.length) {
			var req = new Object();
			for (var i = 0; i < m.args.length; i++) {
				req[m.args[i]] = args[i];
			}
			
			var resObj = this.asckt.postObject(this.url + '/' + m.name, req);
			return (resObj);
		}
	}
	
}

function wsc_invokeMethod(wsc, methodName, args) {
	var wsclientObj = eval(wsc);
	return wsclientObj.invoke(methodName, args);
}

//wsc_invokeMethod(12);


function wsc_getMethods(wsc, xmlDom) {
	var res = new Array();
	for (var i = 0;  i < xmlDom.childNodes.length; i++) {
		
		if (parseInt(xmlDom.childNodes[i].nodeType) == 1) {
			// codice per IE per PC
			if (document.all) {
				var nodesDefs = xmlDom.childNodes[i].selectNodes('/wsdl:definitions/wsdl:types/s:schema/s:element');
				// ciclo per tutti i nodi
				for (var j = 0; j < nodesDefs.length; j++) {
					// sequenza
					var methodName = nodesDefs[j].getAttribute('name');
					if (methodName.substr(methodName.length - 8) != 'Response') {
						var wsM = new webServiceMethod(methodName, wsc);
						var argNodes = nodesDefs[j].selectNodes('s:complexType/s:sequence/s:element');
						for (var k = 0; k < argNodes.length; k++) {
							var argName = argNodes[k].getAttribute('name');
							// ciclo per tutti gli elementi
							wsM.args[wsM.args.length] = argName;
						}
						
						
						res[res.length] = wsM;
						
					}
				}
			} else {
			
			}
		}
		
		
	}
	
	return res;
}

function wsc_mozGetMethods(nodes) {
	
}


function ajax(ajaxName) {

	// controllo se e' specificato il nome dell'oggetto
	if (ajaxName)
		this.name = ajaxName;
	else	
		this.name = 'asocket';

	this.asyncronous = true;
	this.goCB = null;

	var A;
	try {
		A=new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
		try {
			A=new ActiveXObject("Microsoft.XMLHTTP");
		} catch (oc) {
			A=null;
		}
	}
	if(!A && typeof XMLHttpRequest != "undefined")
		A = new XMLHttpRequest();
		
		
		
	// controllo che piattaforma e'
	if (A) {
		this.available = true;
	} else {
		this.available = false;
	}
	
	// distruggo l'oggetto
	this.ajaxObject = A;

	this.init = function() {
		
		// controllo che piattaforma e' Microsoft uso XMLHttp
		var A;
		try {
			A = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				A = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (oc) {
				A = null;
			}
		}
		if(!A && typeof XMLHttpRequest != "undefined")
			A = new XMLHttpRequest();
		
		return A;	
	}

	this.getXml = function(remoteCall) {
		var ajaxObj = this.ajaxObject;
		// controllo se l'oggetto esiste
		if (ajaxObj) {
		
			var aj = this;
		
			ajaxObj.open("GET", remoteCall, false);
			ajaxObj.send("");
			
			var xmlRes = ajaxObj;
			
			// restituisco l'xml
			return xmlRes;
		}
	}

	this.getResponse = function(remoteCall, cb, getObj) {
		
		var ajaxObj = null;
		if (this.ajaxObject) {
			this.init();
			ajaxObj = this.ajaxObject;
	 	} else {
			ajaxObj = this.ajaxObject;
		}
		
		// controllo se l'oggetto esiste
		if (ajaxObj) {
		
			var aj = this;
			
			
			
			ajaxObj.open("GET", remoteCall, this.asyncronous);
			
			
			ajaxObj.setRequestHeader("Method", "GET " + remoteCall + " HTTP/1.1");
			//ajaxObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			
			
			// controllo se e' asincrono
			if (this.asyncronous) {
				ajaxObj.onreadystatechange = function() {
					if (ajaxObj.readyState != 4) 
						return;
					
					var status;
					var data;
					
					aj.status = ajaxObj.status;
					
					if (getObj) {
						// nodi sotto root cnAjax
						cb(aj, ajaxObj);
					} else {
						cb(ajaxObj.responseText);
					}
					if (!document.all) {
						delete ajaxObj;
						delete this.ajaxObject;
						this.ajaxObject = null;
					}
				}
			}
			
			
			
			ajaxObj.send("");
			
			
			
			if (!this.asyncronous) {
				// restituisco i dati in maniera sincrona rispetto 
				// alla chiamatata del metodo
				if (!getObj) {
					var data = ajaxObj.responseText;
					
					return data;
				} else {

					var resObject = ajax_responseXmlToObject((ajaxObj.responseXML && ajaxObj.responseXML.childNodes.length) ? ajaxObj.responseXML : ajaxObj.responseText);
					
					return resObject;
				}
			}
			
			
			
		}
		
		
	}
	
	this.getObject = function(remoteCall, cb) {
	
		if (this.asyncronous) {
			if (cb)
				this.goCB = cb;
			else
				this.goCB = this.callBackFunction;
			
			this.getResponse(remoteCall, ajax_getObjectCB, true);
		} else {
			// restituisco l'oggetto
			return this.getResponse(remoteCall, null, true);
		}
	}
	
	this.getObjectCB = function(nodes) {
		this.goCB(ajax_responseXmlToObject(nodes, this.name, this.status));
		//this.goCB = null;
	}
	
	
	this.postObject = function(remoteCall, o, cb) {
		
		var ajaxObj = null;
		if (this.ajaxObject) {
			this.init();
			ajaxObj = this.ajaxObject;
	 	} else {
			ajaxObj = this.ajaxObject;
		}
	
		if (cb)
			this.goCB = cb;
		
		// ciclo per tutte le proprieta
		var urlEncoded = '';
		
		for (prop in o) {
			
			// Firefox 1.0.7 o prec non implementa
			// instanceof correttamente su MacOs X
			// uso questo workaround sperando che il problema
			// venga risolto con la versione 1.5
			
			//if (o[prop] instanceof Array) {
			
			if (typeof(o[prop]) != 'function') {
				if (o[prop] && o[prop].join) {
					for (var i = 0; i < o[prop].length; i++) {
						urlEncoded += '&'+prop+'='+escape(o[prop][i]);
					}
				} else {
					urlEncoded += '&'+prop+'='+escape(o[prop]);
				}
			}
		}

		// tolgo il primo carattere &
		urlEncoded = urlEncoded.substr(1);

	
			
	
		
		var ajaxObj = this.ajaxObject;
		var aj = this;
		// controllo se l'oggetto esiste
		if (ajaxObj) {
			
			
			// imposto gli header http appropriati
			ajaxObj.open("POST", remoteCall, this.asyncronous);
			ajaxObj.setRequestHeader("Method", "POST " + remoteCall + " HTTP/1.1");
			ajaxObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			ajaxObj.setRequestHeader("Content-Length", urlEncoded.length);
			
			
			// controllo se e' asincrono
			if (this.asyncronous) {
				ajaxObj.onreadystatechange = function() {
					if (ajaxObj.readyState != 4) 
						return;
						
					aj.status = ajaxObj.status;
					
					// nodi sotto root cnAjax
					ajax_getObjectCB(aj, ajaxObj);
					
					if (!document.all) {
						delete ajaxObj;
						delete this.ajaxObject;
						this.ajaxObject = null;
					}
						
					
				}
			}
			
			try {
			    ajaxObj.send(urlEncoded);
			} catch (e) {
			    if (this.onError)
			        this.onError(e);
			}

			
			if (!this.asyncronous) {
				// restituisco i dati in maniera sincrona rispetto 
				// alla chiamatata del metodo
				
				var resObject = null;
				try {

					resObject = ajax_responseXmlToObject((ajaxObj.responseXML && ajaxObj.responseXML.childNodes.length) ? ajaxObj.responseXML : ajaxObj.responseText);

					
				} catch (e) {

				}
				return resObject;
			}
			
			
			
		}
	
	}
	
	//this.callBackFunction = null;
}

function ajax_responseXmlToObject(xmlResponse, ajaxName, status) {
	
	
	var d = new Date();
	///try {console.log(d.getSeconds() + ' ' + d.getMilliseconds());} catch (e) {};

	if (xmlResponse.childNodes) {
	
		//try {console.log('XMLResponse');} catch (e) {};

		for (var i = 0; i < xmlResponse.childNodes.length; i++) {

			if (parseInt(xmlResponse.childNodes[i].nodeType) == 1) {
				var nodeName = xmlResponse.childNodes[i].nodeName;
				if ((nodeName == 'cnAjax') || (nodeName == 'ca') || (nodeName == 'hyphenAjax')) {
					var res = ajax_xmlToObject(xmlResponse.childNodes[i].childNodes, nodeName == 'ca');
					var d = new Date();
					//try {console.log(d.getSeconds() + ' ' + d.getMilliseconds());} catch (e) {};
					//try {console.log(res);}catch(e) {};
					return res;
					break;
				} else {
					// xml semplice: provo a trasformarlo in oggetto
					if (xmlResponse.childNodes[i].nodeName && (xmlResponse.childNodes[i].nodeName != '#comment') && (xmlResponse.childNodes[i].nodeName != 'xml')) {
						return ajax_simpleXmlToObject(xmlResponse.childNodes[i].childNodes);
						break;
					}
				}
			}
		}
		
		return null;
	} else {
		// oggetto javascript
		// .split('\'').join('\\\'')
		try {
			res = eval('___o = ' + xmlResponse);
		} catch (exc) {
		
		
		
		    var e = new Object();
		    e.name = 'Ajax Error: '+ajaxName + ' status(' + status + ')';
		    e.message = xmlResponse;
		    e.stack = 'ajax_responseXmlToObject';
		    exception(e);
		    try{console.log(e)}catch(e1){};
			res = null;
			
			
		}
		
		var d = new Date();
		//try {console.log(d.getSeconds() + ' ' + d.getMilliseconds());} catch (e) {};
		//try {console.log(res);}catch(e) {};
		
		return res;
	}
	
	

	
}


function ajax_simpleXmlToObject(xmlNodes) {
	var res = new Object();
	var atLeastOne = false;
	for (var i = 0; i < xmlNodes.length; i++) {
		if (parseInt(xmlNodes[i].nodeType) == 1) {
			// controllo se ha altri nodi
			atLeastOne = true;
			if (xmlNodes[i].childNodes.length > 1) {
				res[xmlNodes[i].nodeName] = ajax_simpleXmlToObject(xmlNodes[i].childNodes);
			} else {
				res[xmlNodes[i].nodeName] = ajax_getNodeValue(xmlNodes[i]);	
			}
		}
	}
	
	if (!atLeastOne) {
		// lettura risultato
		res = (xmlNodes[0].nodeValue);
	}
	
	
	return res;
}

function ajax_xmlToObject(xmlNodes, shortForm) {
	var res = new Object();
	// ciclo per tutti i nodi
	for (var i = 0; i < xmlNodes.length; i++) {
		if (parseInt(xmlNodes[i].nodeType) == 1) {
			var objValue = null;
			var xType = xmlNodes[i].getAttribute(shortForm ? 't' : 'xtype');
			
			if (!xType)
				xType = xmlNodes[i].getAttribute('type');
			
			switch (xType) {
			case 'Var':		// variabile "variant"
			case 'V':		
				objValue = ajax_getNodeValue(xmlNodes[i]);
				if (objValue != null) {
					if (isNaN(objValue)) {
						if ((objValue.toLowerCase() == 'false') || (objValue.toLowerCase() == 'true')) {
							objValue = objValue.toLowerCase() == 'true';
							
						}
					} else {
						objValue = parseFloat(objValue);
					}
				}
				break;
			case 'Real':
			case 'R':
				objValue = ajax_getNodeValue(xmlNodes[i]);
				objValue = parseFloat(objValue);
				break;
			case 'Int':
			case 'I':
				objValue = ajax_getNodeValue(xmlNodes[i]);
				objValue = parseInt(objValue);
				break;
			case 'Bool':
			case 'B':
				objValue = ajax_getNodeValue(xmlNodes[i]);
				objValue = (objValue == '1') || (objValue == 'true') || (objValue == 'True');
				break;
			case 'String':
			case 'S':
				objValue = ajax_getNodeValue(xmlNodes[i]);
			
				//objValue = xmlNodes[i].firstChild.nodeValue;
				break;
			case 'Array':
			case 'A':
				objValue = new Array();
				var thisNodes = xmlNodes[i].childNodes;
				if (thisNodes) {
					for (var j = 0; j < thisNodes.length; j++) {
						// controllo se e' un elemento
						if (parseInt(thisNodes[j].nodeType) == 1) {
							objValue[objValue.length] = ajax_xmlToObject(thisNodes[j].childNodes, shortForm);
						}
					}
				}
				break;
			case 'IntArray':
			case 'IA':
				objValue = new Array();
				var thisNodes = xmlNodes[i].childNodes;
				if (thisNodes) {
					for (var j = 0; j < thisNodes.length; j++) {
						// controllo se e' un elemento
						if (parseInt(thisNodes[j].nodeType) == 1) {
							objValue[objValue.length] = parseInt(ajax_getNodeValue(thisNodes[j]));
						}
					}
				}
				break;
			case 'StringArray':
			case 'SA':
				objValue = new Array();
				var thisNodes = xmlNodes[i].childNodes;
				if (thisNodes) {
					for (var j = 0; j < thisNodes.length; j++) {
						// controllo se e' un elemento
						if (parseInt(thisNodes[j].nodeType) == 1) {
							objValue[objValue.length] = ajax_getNodeValue(thisNodes[j]);
						}
					}
				}
				break;
			case 'Object':
			case 'O':
				objValue = ajax_xmlToObject(xmlNodes[i].childNodes, shortForm);
				break;
			default:
				objValue = ajax_getNodeValue(xmlNodes[i]);
				//objValue = xmlNodes[i].firstChild.nodeValue;
				break;
			}
			res[xmlNodes[i].getAttribute(shortForm ? 'n' : 'name')] = objValue;
		}
	}
	return res;	
}

// funzione per lettura valore del nodo xml
function ajax_getNodeValue(node) {
	
	var objValue = null;
	if (node.childNodes.length > 1) {
		objValue = node.childNodes[1].nodeValue;
	} else {
		try {
			objValue = node.firstChild.nodeValue;
		} catch (e) {
			objValue = null;
		}
	}
	
	return objValue;
	
}

function ajax_getObjectCB(ajObj, xml) {
	ajObj.getObjectCB((xml.responseXML && xml.responseXML.childNodes.length) ? xml.responseXML: xml.responseText);
	
} 