// $id
//$Date = 01/12/2005

//Get userAgent
var AGENT_WI_NET = navigator.userAgent.toLowerCase();
var webserviceQueue = new Array();
var webservicePending = 0;
var idTimeout = null;


function Wsjavascript_getXmlHttp()
{
    var xmlhttp;
	
	if (window.XMLHttpRequest)
	{
          // If IE7, Mozilla, Safari, etc: Use native object
          try
          {
			xmlhttp = new XMLHttpRequest();
		  }
		  catch(e)
		  {
		  }
	}
	else
	{
		try 
		{
			xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) 
		{
			try 
			{
				xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch (E) 
			{
				xmlhttp=false;
			}
		}
	}

    return xmlhttp;
}

function pickRecentProgID(idList)
{
	// found progID flag
	var bFound = false;
	for(var i=0; i < idList.length && !bFound; i++)
	{
		try
		{
			var oDoc = new ActiveXObject(idList[i]);
			o2Store = idList[i];
			bFound = true;
		}
		catch (objException)
		{
			// trap; try next progID
		}
	}
	if (!bFound) return "";
	idList = null;
	return o2Store;
};

_SARISSA_DOM_PROGID = pickRecentProgID(["Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);

function Wsjavascript_getDomDocument (rootNodeName)
{
      var oDoc = null;
      oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
      
      try {
      if (oDoc == null)
            oDoc = document.implementation.createDocument("", sName, null);
      } catch (ex) {}

      // if a root tag name was provided, we need to load it in the DOM
      if (oDoc && rootNodeName)
      {
            oDoc.loadXML("<" + rootNodeName + "/>");
      }
      return oDoc;
}

function Wsjavascript_GetSoapParameters(paramsList)
{
	var entete = new Array();
	for (var i = 0; i < paramsList.length; i++)
    {
        var currentParam = paramsList[i];
    
        var objType = typeof(currentParam.value);
        
		switch(objType)
		{
			case "undefined" :
				entete.push("<");
                entete.push(currentParam.name);
                entete.push("></");
                entete.push(currentParam.name);
                entete.push(">");
				break;
			case "string" :
			case "number" :
			case "boolean" :
				if (paramsList[i].doNotEncode == true)
                {
					entete.push("<");
                    entete.push(currentParam.name);
                    entete.push(">");
                    entete.push(currentParam.value);
                    entete.push("</");
                    entete.push(currentParam.name);
                    entete.push(">");
                }
				else
                {
					entete.push("<");
                    entete.push(currentParam.name);
                    entete.push(">");
                    entete.push(XMLEncode(currentParam.value));
                    entete.push("</");
                    entete.push(currentParam.name);
                    entete.push(">");
                }
				break;
			case "object" :
				if (currentParam.value == null)
				{
					entete.push("<");
                    entete.push(currentParam.name);
                    entete.push("></");
                    entete.push(currentParam.name);
                    entete.push(">");
				}
				else if (currentParam.value instanceof Date)
				{
                    entete.push("<");
                    entete.push(currentParam.name);
                    entete.push(">");
                    entete.push(escape(currentParam.value.getTime()));
                    entete.push("</");
                    entete.push(currentParam.name);
                    entete.push(">");
				}
				else if (currentParam.value instanceof Array)
				{
					entete.push("<");
                    entete.push(currentParam.name);
                    entete.push(">");
                    
                    var className = "";
                    if (currentParam.value.length > 0)
                    {
                        if (typeof(currentParam.value[0].getClass) == "function")
                        {
                            className = currentParam.value[0].getClass();
                        }
                    }
                    
					for (var j = 0; j < currentParam.value.length; j++)
					{
                        var subParam = currentParam.value[j];
                    
						var type = typeof(subParam);
                        
						if (type == "number") type = "int";
                        else if (className != "") type = "obj";
                        
						switch(type)
						{
                            case "obj" :
                                var subArray = new Array();
								subArray.push(new WSParams(className, subParam, currentParam.doNotEncode));
								entete.push(Wsjavascript_GetSoapParameters(subArray));
                                break;
							case "string" :
							case "int" :
							case "boolean" :
								if (currentParam.doNotEncode == true)
								{
									entete.push("<");
                                    entete.push(type);
                                    entete.push(">");
                                    entete.push(subParam);
                                    entete.push("</");
                                    entete.push(type);
                                    entete.push(">");
								}
								else
								{
									entete.push("<");
                                    entete.push(type);
                                    entete.push(">");
                                    entete.push(XMLEncode(subParam));
                                    entete.push("</");
                                    entete.push(type);
                                    entete.push(">");
								}
								break;
							default :
                                break;
						}
					}

					entete.push("</");
                    entete.push(currentParam.name);
                    entete.push(">");
				}
				else // object
				{
					entete.push("<");
                    entete.push(currentParam.name);
                    entete.push(">");
                    
					var subArray = new Array();
					for (var n in currentParam.value)
					{
                        if (n == "getClass") continue;
                        
						var subParam = new WSParams(n, currentParam.value[n], currentParam.doNotEncode);
						subArray.push(subParam);
					}
					entete.push(Wsjavascript_GetSoapParameters(subArray));
					entete.push("</");
                    entete.push(currentParam.name);
                    entete.push(">");
				}
				break;
			case "function" :
				break;
			default :
				throw new Exception("WsJavascriptException", "invalid object type found for serialization");
        }
    }
    
	return entete.join("");
}

function Wsjavascript_CreateSoap(url, wsFunction, paramsList, uriName, guid)
{
    var entete = new Array();

    entete.push("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    
    entete.push("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
    entete.push("<soap:Body>");

    entete.push("<");
    entete.push(wsFunction);
    entete.push(" xmlns=\"");
    entete.push(concatUrl( checkUrl(uriName), "/"));
    entete.push("\">");

    if (guid != null)
    {
        entete.push("<");
        entete.push(guid.name);
        entete.push(">");
        entete.push(guid.value);
        entete.push("</");
        entete.push(guid.name);
        entete.push(">");
    }

    if (paramsList != null)
    {
        entete.push(Wsjavascript_GetSoapParameters(paramsList));
    }

    entete.push("</");
    entete.push(wsFunction);
    entete.push(">");
    entete.push("</soap:Body></soap:Envelope>");

    return entete.join("");
}


///url : url of webservice to call
///fctHandler : function to call for response (could be null)
///wsFunction : webservice function to call
///paramsList : list of params to call (array of WSParams object)
function SendRequest(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler)
{
	if (url == "")
	{
		alert("Error while calling function " + wsFunction);
		return;
	}

    if (typeof(fctHandler) == "undefined") fctHandler = null;
    if (typeof(wsFunction) == "undefined") wsFunction = null;
    if (typeof(paramsList) == "undefined") paramsList = null;
    if (typeof(uriName) == "undefined") uriName = null;
    if (typeof(timeout) == "undefined") timeout = 5; //5 secondes
	if (typeof(timeoutHandler) == "undefined") timeoutHandler = null;

    var wsObj = new WsObject(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler, 0, null);

    if (webservicePending != 0)
    {
        webserviceQueue.unshift(wsObj);
    }
    else
    {
		var xmlhttp = Wsjavascript_getXmlHttp();
		
        xmlhttp.open("POST", url, true);

        xmlhttp.onreadystatechange = function (e)
        {
            if (xmlhttp.readyState == 4) //don't call function when response isn't totally ready
            {
                WebserviceResponse(xmlhttp, fctHandler, timeoutHandler, wsFunction);
                xmlhttp = null;
            }
        };

        xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlhttp.setRequestHeader("User-Agent", "wsjavascript_" + wsFunction);
		xmlhttp.setRequestHeader("Content-Encoding", "utf-8");

		var entete;
		if (wsFunction != "none")
		{
        xmlhttp.setRequestHeader("SOAPAction" , concatUrl( checkUrl(uriName), wsFunction) );
			entete = Wsjavascript_CreateSoap(url, wsFunction, paramsList, uriName);
		}
		else
		{
			entete = paramsList;
		}

        xmlhttp.send(entete);

        if (timeout != 0)
        {
			idTimeout = setTimeout(function() {TestWebserviceTimeout(xmlhttp, wsFunction);}, timeout * 1000);
		}

        webservicePending++;
        entete = null;
        uriName = null;
    }
}

///url : url of webservice to call
///fctHandler : function to call for response (could be null)
///wsFunction : webservice function to call
///paramsList : list of params to call (array of WSParams object)
function XmlRequest(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler)
{
	if (url == "")
	{
		alert("Error while calling function " + wsFunction);
		return;
	}

    if (typeof(fctHandler) == "undefined") fctHandler = null;
    if (typeof(wsFunction) == "undefined") wsFunction = null;
    if (typeof(paramsList) == "undefined") paramsList = null;
    if (typeof(uriName) == "undefined") uriName = null;
    if (typeof(timeout) == "undefined") timeout = 5; //5 secondes
	if (typeof(timeoutHandler) == "undefined") timeoutHandler = null;

    var wsObj = new WsObject(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler, 2, null);

    if (webservicePending != 0)
    {
        webserviceQueue.unshift(wsObj);
    }
    else
    {
		var xmlhttp = Wsjavascript_getXmlHttp();
		
        xmlhttp.open("POST", url, true);
	
        xmlhttp.onreadystatechange = function (e)
        {
            if (xmlhttp.readyState == 4) //don't call function when response isn't totally ready
            {
                WebserviceResponseXml(xmlhttp, fctHandler, timeoutHandler, wsFunction, uriName);
                xmlhttp = null;
            }
        };

        xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlhttp.setRequestHeader("User-Agent", "wsjavascript_xml_" + wsFunction);
		xmlhttp.setRequestHeader("Content-Encoding", "utf-8");

		var entete;
		if (wsFunction != "none")
		{
			xmlhttp.setRequestHeader("SOAPAction" , concatUrl( checkUrl(uriName), wsFunction) );
			entete = Wsjavascript_CreateSoap(url, wsFunction, paramsList, uriName);
		}
		else
		{
			entete = paramsList;
		}

        xmlhttp.send(entete);

        if (timeout != 0)
        {
			idTimeout = setTimeout(function() {TestWebserviceTimeout(xmlhttp, wsFunction);}, timeout * 1000);
		}

        webservicePending++;
        entete = null;
        uriName = null;
    }
}

function SendAsyncRequest(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler, stepHandler, guidParams)
{
	if (url == "")
	{
		alert("Error while calling function " + wsFunction);
		return;
	}
	

    if (typeof(fctHandler) == "undefined") fctHandler = null;
    if (typeof(wsFunction) == "undefined") wsFunction = null;
    if (typeof(paramsList) == "undefined") paramsList = null;
    if (typeof(uriName) == "undefined") uriName = null;
    if (typeof(timeout) == "undefined") timeout = 5; //5 secondes
	if (typeof(timeoutHandler) == "undefined") timeoutHandler = null;
    if (typeof(stepHandler) == "undefined") stepHandler = null;

    if ((typeof(guidParams) == "undefined") || (guidParams == null))
    {
        guidParams = "";
    }

    var wsObj = new WsObject(url, fctHandler, wsFunction, paramsList, uriName, timeout, timeoutHandler, 1, stepHandler);
    wsObj.setRequestGuid("askId", guidParams);

    if (webservicePending != 0)
    {
        webserviceQueue.unshift(wsObj);
    }
    else
    {
		var xmlhttp = Wsjavascript_getXmlHttp();

        xmlhttp.open("POST", url, true);
	
		
        xmlhttp.onreadystatechange = function (e)
        {
            if (xmlhttp.readyState == 4) //don't call function when response isn't totally ready
            {
                AsyncWebserviceResponse(xmlhttp, wsObj);
                xmlhttp = null;
            }
        };

        xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlhttp.setRequestHeader("User-Agent", "wsjavascript_async_" + wsFunction);
		xmlhttp.setRequestHeader("Content-Encoding", "utf-8");

		var entete;
		if (wsFunction != "none")
		{
			xmlhttp.setRequestHeader("SOAPAction" , concatUrl( checkUrl(uriName), wsFunction) );
			entete = Wsjavascript_CreateSoap(url, wsFunction, paramsList, uriName, wsObj.guidParam);
		}
		else
		{
			entete = paramsList;
		}

        xmlhttp.send(entete);
        if (timeout != 0)
        {
			idTimeout = setTimeout(function() {TestWebserviceTimeout(xmlhttp, wsFunction);}, timeout * 1000);
		}
        webservicePending++;
        entete = null;
        uriName = null;
    }
}


function TestWebserviceTimeout(xmlhttp, wsFunction)
{
    idTimeout = null;

    if (xmlhttp.readyState == 1)
    {
        xmlhttp.abort();
    }
}

function WebserviceResponse(xmlhttp, fctHandler, errorHandler, wsFunction)
{
    if (idTimeout != null)
    {
        clearTimeout(idTimeout);
        idTimeout = null;
    }

	var xmlResponse = ( (xmlhttp.responseXML) && (xmlhttp.responseXML.childNodes.length > 0) );
	
	
    //WebService send a response : get obj
	var response = (xmlResponse) ? xmlhttp.responseXML.getElementsByTagName("ns1:" + wsFunction + "Response") : xmlhttp.responseText;
	if (response.length == 0) response = xmlhttp.responseXML.getElementsByTagName(wsFunction + "Response");
	
    if (xmlhttp.status != 200)
    {
		if (errorHandler != null)
		{
			errorHandler(xmlhttp.status, xmlhttp.statusText, xmlhttp.responseXML);
            fctHandler(null);
		}
		else if (fctHandler != null)
		{
			fctHandler(null);
		}

		WsJavascript_CallNext();
		return;
    }

    if (fctHandler != null)
    {

		if (xmlResponse)
		{
		if (response.length == 0)
		{
			fctHandler(null);
		}
		else
		{
			response = response[0];
            var array = Parse(response.childNodes, null);
		    fctHandler(array);
		}
    }
		else
		{
			fctHandler(response);
		}
	}

    WsJavascript_CallNext();
}

function WebserviceResponseXml(xmlhttp, fctHandler, errorHandler, wsFunction, uriName)
{
    if (idTimeout != null)
    {
        clearTimeout(idTimeout);
        idTimeout = null;
    }

    if (xmlhttp.status != 200)
    {
		if (errorHandler != null)
		{
			errorHandler(xmlhttp.status, xmlhttp.statusText, xmlhttp.responseXML);
		}
		else if (fctHandler != null)
		{
			fctHandler(null);
		}

		WsJavascript_CallNext();
		return;
    }

	var response = xmlhttp.responseXML.getElementsByTagName(wsFunction + "Result");

	if (fctHandler != null)
	{
		if (response.length == 0)
		{
			fctHandler(null);
		}
		else
		{
			response = response[0];
			if (response.childNodes.length>1)
				fctHandler(response.childNodes, response);
			else
				fctHandler(response.firstChild, response);
		}
	}

    WsJavascript_CallNext();
}

function AsyncWebserviceResponse(xmlhttp, webservObject)
{
    if (idTimeout != null)
    {
        clearTimeout(idTimeout);
        idTimeout = null;
    }

    //WebService send a response : get obj
	var response = xmlhttp.responseXML.getElementsByTagName(webservObject.wsFunction + "Result");

    if (xmlhttp.status != 200)
    {
		if (webservObject.errorHandler != null)
		{
			webservObject.errorHandler(xmlhttp.status, xmlhttp.statusText, xmlhttp.responseXML);
		}
		else if (webservObject.fctHandler != null)
		{
			webservObject.fctHandler(null);
		}

		WsJavascript_CallNext();
		return;
    }


	if ((response.length == 0) && (webservObject.fctHandler != null))
    {
        webservObject.fctHandler(null);
    }

    else if (response.length != 0)
    {
		var array = null;

        response = response[0];
		if (response.childNodes.length>1)
			array = initParseXml(response.childNodes);
		else
			array = initParseXml(response.firstChild);

		if ((array.state == 2) || (array.state == 3))
        {
			if (webservObject.fctHandler != null)
			{
				if (response.childNodes.length > 1)
					webservObject.fctHandler(response.childNodes);
				else
					webservObject.fctHandler(response.firstChild);
			}
        }
        else
        {
			if (webservObject.stepHandler != null) webservObject.stepHandler(array.state);
			setTimeout(function() { SendAsyncRequest(webservObject.url, webservObject.fctHandler, webservObject.wsFunction, webservObject.paramsList, webservObject.uriName,webservObject.timeout, webservObject.timeoutHandler, webservObject.stepHandler, array.UniqueId); }, 2000);
        }
    }

    WsJavascript_CallNext();
}

function WsJavascript_CallNext()
{
    webservicePending--;
    if (webserviceQueue.length > 0)
    {
        var obj = webserviceQueue.pop();
        if (obj.method == 0)
        {
            SendRequest(obj.url, obj.fctHandler, obj.wsFunction, obj.paramsList, obj.uriName, obj.timeout, obj.errorHandler, obj.stepHandler);
        }
        else if (obj.method == 1)
        {
            SendAsyncRequest(obj.url, obj.fctHandler, obj.wsFunction, obj.paramsList, obj.uriName, obj.timeout, obj.timeoutHandler, obj.stepHandler, obj.guidParam.value);
        }
        else
        {
			XmlRequest(obj.url, obj.fctHandler, obj.wsFunction, obj.paramsList, obj.uriName, obj.timeout, obj.errorHandler, obj.stepHandler);
        }
    }
}

function Parse(element, array)
{
	for (var i = 0; i < element.length; i++)
	{
		if (element[i].childNodes.length > 1)
		{
			if (array != null)
			{
				array.push(Parse(element[i].childNodes, new Array()));
			}
			else
			{
				array = Parse(element[i].childNodes, new Array());
			}
		}
		else if (element[i].childNodes.length > 0)
		{
            if (array == null) array = new Array();

            if ((element[i].childNodes[0].childNodes.length > 0) && (element[i].childNodes[0].nodeValue == null))
            {
				array.push(Parse(element[i].childNodes[0].childNodes, new Array()));
            }
            else if (element[i].childNodes[0].nodeValue == null)
            {
				array.push(new Array());
            }
            else
            {
				try {
					value = decodeWS(element[i].childNodes[0].nodeValue);
                }
                catch(e)
                {
					value = element[i].childNodes[0].nodeValue;
                }
				array.push(value);
                array[element[i].nodeName] = value;
			}
		}
		else
		{
			if (array != null)
				array.push("");
		}
	}

	return array;
}

function initParseXml(current, type) {

	if ( !current ) return type=='array'?new Array():null;
	// Quelque soit ce que nous envoi XMLResult, on recupere le tag XxxxResponse
	current = current.nodeType?current.parentNode:current[0].parentNode;
	return parseXml(current, type);
}

function parseXml(current, type) {
	var firstChild = current.childNodes[0];

	if ( current.childNodes.length==1
		&& (firstChild.nodeType==3	|| firstChild.nodeType==4)  ) {

		// Nous somme sur un scalaire
		return firstChild.nodeValue;

	} else if ( type=='array'
		|| ( current.childNodes.length>1 && firstChild.nodeName==firstChild.nextSibling.nodeName ) ) {

		// Nous somme donc dans un tableau
		var obj = new Array();
		var child = firstChild;
		while ( child ) {
			obj.push( parseXml(child) );
			child = child.nextSibling;
		}
		return obj;

	} else if ( type=='object' || current.childNodes.length>1 ) {

		// Nous somme dans un objet
		var obj = new Object();
		var child = firstChild;
		while ( child ) {
			obj[child.nodeName] = parseXml(child);
			child = child.nextSibling;
		}
		return obj;

	} else if ( current.childNodes.length==1 ) {

		// Nous somme sur un tableau ou un objet avec un seul element.
		var obj = new Array();
		obj.push( parseXml(firstChild) );
		obj[current.nodeName] = obj[0];
		return obj;
	}
}

/********** UTILS *************/
function decodeWS(str)
{
	str = decodeURI(str);
	var reg = new RegExp("_/POURCENT/_", "gi");
	str = str.replace(reg, "%");
	return str;
}

function XMLEncode(str)
{
	try
	{
		str = str.replace(/\&/gi, "&amp;");
		str = str.replace(/>/gi, "&gt;");
		str = str.replace(/</gi, "&lt;");
	}
	catch(e) {}
	return str;
}

function WSParams(name, value, doNotEncode)
{
    this.name = name;
    this.value = value;
    if ((typeof(doNotEncode) != "undefined") && (doNotEncode != null))
    {
        this.doNotEncode = doNotEncode;
    }
    else
    {
        this.doNotEncode = false;
    }
}

function ParameterObject(name, array)
{
	this.name = name;
	this.parameters = array;
}

function XMLExeption(message, errorCode)
{
	this.Message = message;
	this.code = errorCode;
}

//Method : 0 : direct, 1 : async
function WsObject(url, fctHandler, wsFunction, paramsList, uriName, timeout, errorHandler, method, stepHandler)
{
    this.url = url;
    this.fctHandler = fctHandler;
    this.wsFunction = wsFunction;
    this.paramsList = paramsList;
    this.uriName = uriName;
    this.timeout = timeout;
    this.errorHandler = errorHandler;
    this.method = method;
    this.stepHandler = stepHandler;
    this.guidParam = null;
}

WsObject.prototype.setRequestGuid = function(param, val)
{
    this.guidParam = new WSParams(param, val);
};

function defaultErrorHandler(statusCode, statusText, xmlError) {
	var faultS = xmlError?xmlError.getElementsByTagName("faultstring")[0]:null;
	var faultA = xmlError?xmlError.getElementsByTagName("faultactor")[0]:null;
	if ( faultS!=null && faultA!=null )
		alert('** Error **\n'+faultS.firstChild.nodeValue+'\n\n ** At **\n'+faultA.firstChild.nodeValue);
	else if ( faultS!=null )
		alert('** Error **\n'+faultS.firstChild.nodeValue);
	else
		alert('** Error **\n'+statusCode+", "+statusText);
}

function checkUrl(urlName) {
	if ( urlName.indexOf('http')==0 )
		return urlName;
	else
		return 'http://'+urlName;
}

function concatUrl(url1, url2) {
	if (url1.length==0)
		return url2;
	else if (url2.length==0)
		return url1;
	else if ( url1.charAt(url1.length-1)=='/' && url2.charAt(0)=='/' )
		return url1+url2.substring(1);
	else if ( url1.charAt(url1.length-1)=='/' || url2.charAt(0)=='/' )
		return url1+url2;
	else {
		return url1+'/'+url2;
	}
}