/************* GLOBALS ***************/
var xsi99 = "http://www.w3.org/1999/XMLSchema-instance";
var xsi01 = "http://www.w3.org/2001/XMLSchema-instance";
var xsd01 = "http://www.w3.org/2001/XMLSchema";
var xsd99 = "http://www.w3.org/1999/XMLSchema";
var _st = new Array();
_st["int"] = 0;
_st["integer"] = 0;
_st["float"] = 0;
_st["double"] = 0;
_st["byte"] = 0;
_st["decimal"] = 0;
_st["long"] = 0;
_st["short"] = 0;
_st["unsignedByte"] = 0;
_st["unsignedInt"] = 0;
_st["unsignedShort"] = 0;
_st["unsignedLong"] = 0;
_st["boolean"] = 0;
_st["negativeInteger"] = 0;
_st["enum"] = 1;
_st["QName"] = 1;
_st["string"] = 2;
_st["timeInstant"] = 3;
_st["dateTime"] = 3;
_st["date"] = 4;
_st["time"] = 5;
_st["base64"] = 6;
/************* END GLOBALS ***************/

// Constructor for the WebServiceManager object
function WebServiceManager( serviceUrl ) //was: NextITBaseService
{
	this.OnWsdlParsed = null; // Called after wsdl is parsed
	//this.IsParsed = false; // not used... yet!
	this.OnResult = null;
	this.Async = true;
	
	// Save url to webservice
	this.Url = BuildAbsoluteUrl( serviceUrl );
	
	// Parsed Wsdl properties
	this.Messages = null;
	this.Ports = null;
	this.Bindings = null;
	this.oS = null;
};

// Loads the WSDL XML document into this.XmlDoc (see this.XmlDoc.xml, this will be filled if successful)
WebServiceManager.prototype.LoadXMLDOM = function()
{
	if( this.XmlDoc == null )
	{
		// Build Service
		this.XmlDoc = this.GetXmlDom(); // In NextITXD.js, uses browser detection and gets XML wsdl document
		this.XmlDoc.async = false; // otherwise it wont load in time
		this.XmlDoc.load( this.Url );
	}
	//alert('xml: '+this.XmlDoc.xml); // Mozilla wont load if url is not relative to this script (same base url)
};

// Get the XML loader for this browser
WebServiceManager.prototype.GetXmlDom = function()
{
	var xmlDoc = null;
	if (window.ActiveXObject)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		//xmlDoc.onreadystatechange = this.OnXmlDocStateChanged;
 	}
	else if (document.implementation && document.implementation.createDocument)
	{
		xmlDoc = document.implementation.createDocument("", "", null);
		//xmlDoc.onload = this.OnXmlDocStateChanged;
	}
	else
	{
		return;
	}
	return xmlDoc;
};

/*
// Dont seem to even need this... Since the xml DOM is loaded instantly, and we dont parse until it's requested
WebServiceManager.prototype.OnXmlDocStateChanged = function() // NextITBaseService.prototype.stateChange = function()
{
	if( this.XmlDoc == null )
	{
		return;
	}
	try
	{
		//alert( 'Start ParseWSDL (xmldoc_statechanged) ' + this.XmlDoc.xml );
		this.ParseWsdl();
	}
	catch(e)
	{
		//alert('ParseWsdl failed.'+e.message);
	}
};*/

// Get the object that sends the soap request
function GetXmlHttp()
{
	var xmlhttp = false;
	
	if (window.ActiveXObject)
	{
		xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
	}
	else
	{
		try 
		{ 
			xmlhttp = new XMLHttpRequest();
		}
		catch (e3) 
		{ 
			xmlhttp = false; 
		}
	}
	
	return xmlhttp;
};

// Builds a full path url out of a relative or partial url string
function BuildAbsoluteUrl(relUrl) //BuildServiceUrl
{
	if (relUrl.indexOf("://") > 0)
		return AppendWsdlToUrl(relUrl);
	var baseUrl = document.URL;
	return  AppendWsdlToUrl( baseUrl.substr(0, baseUrl.lastIndexOf("/"))+ "/" + relUrl + (relUrl.indexOf(".")>=0 ? "" : ".asmx?wsdl") );
};

function AppendWsdlToUrl( url )
{
	if( url.indexOf( "wsdl" ) > 0 )
		return url;
	else
		return url += "?wsdl";
};

WebServiceManager.prototype.InvokeMethod = function( wsMethod, cb )
{
	//alert('Calling LoadXMLDOM()');
	this.LoadXMLDOM(); // Load the XMLDOM (moved from constructor, so we don't hit webservice every page load)
	var args = this.InvokeMethod.arguments;
	
	// Build the object used in the _InvokeMethod function
	var call = new Object();
	call.wsFuncName = wsMethod;
	call.cb = cb; // not sure why we have two of these...
	if (this.OnResult)
	{
		this.cb += this.OnResult;
	}
	call.asynchandler = cb; // required when in asyncronous mode
	call.async = this.Async; // again, just copying the main object (this)
	call.args = new Array();
	
	// Use extra parameters for webservice parameters
	for( var i = 2; i < args.length; i++ )
	{
		try
		{
			call.args.push(args[i]);
		}
		catch(e)
		{
			try
			{
				call.args[call.args.length] = args[i];
			}
			catch(e)
			{
				//alert('push on array failed in InvokeMethod');
			}
		}
	}
			
	var bla = this._InvokeMethod(call); // Call internal InvokeMethod
	if (!bla)
	{
		bla = 'asyncronus call occuring'; // Need to return something
	}
	return bla;
};

WebServiceManager.prototype._InvokeMethod = function( oCall )
{
	// If we haven't parsed the Wsdl yet, do it now
	if ( !this.oS )
	{
		//alert('before ParseWsdl: oS='+this.oS);
		this.ParseWsdl();
		//alert('after ParseWsdl: oS='+this.oS);
	}
	if ( !this.oS )
	{
		return ReportError( "couldn't parse wsdl" );
	}
	//alert(this.XmlDoc.xml);
	var xmlHttp = XmlHttp.GetXmlHttp(); // Get the object that sends/recieves the soap request/response
	
	if( xmlHttp == null )
	{
		return ReportError( "XML HTTP IS NULL" );
	}
	
	oCall.portName = this.oS.defPortName;
	var oM = GetMsg( this, oCall, oCall.args );
	var szParams = null;
	
	if (oM != null)
	{
		szParams = EncodeArgs(oM, this, oCall.args, 0); //(cb == null)? false : true;
	}
	
	if (szParams == null)
	{
		callNext(this.oS);
		//return returnError(oCall, 0);
		return "Error 0";
	}
	oCall.fRpc = oM.fRpc;
	oCall.fLiteral = oM.fLiteral;
	oCall.response = oM.response;
	var oP = this.oS.soapPort[oCall.portName];

	try
	{
		// for IE, we do not need to load things as asynchronus, because the ActiveXObject
		// is to fast to stop or worry about :P
		//alert('username:'+co.userName + '\r\nloacation:'+oP.location+ '\r\nAsync:'+this.Async);
		if (oCall.userName == null)
		{
			try
			{
				if ( (this.Async == true) && (_CONSTANT_OLDSCHOOL_IEXPLORER == false) )
				{
					xmlHttp.open("POST", oP.location, true);
				}
				else
				{
					xmlHttp.open("POST", oP.location, false);
				}
			}
			catch(e)
			{ 
				//alert('exception in open'); 
			}
		}
		else
		{
			xmlHttp.open("post", oP.location, oCall.async, oCall.userName, oCall.password == null ? "" : co.password);
		}
	}
	catch (e)
	{
		//return returnError(oCall, 5);
		return "Error 5";
	}
	
	var szAction = oM.soapAction;
	if (szAction != null && szAction.length > 0)
	{
		xmlHttp.setRequestHeader("SOAPAction", '"'+szAction+'"');
	}
	else // need a SOAPAction header for Java webservices
	{
		xmlHttp.setRequestHeader("SOAPAction", '""');
	}
	xmlHttp.setRequestHeader("Content-Type", "text/xml");
	var sNS = "";
	for (var ns in this.oS.ns)
	{
		sNS +=  " xmlns" + (ns==''?'':':') + ns + '="' + this.oS.ns[ns] + '"';
	}
	szHeader = "";
	var sh = oCall.SOAPHeader == null ? this.oS.SOAPHeader : oCall.SOAPHeader;
	var ht = (oM.headers == null) ? this.oS.headers : oM.headers;
	//alert('part 4');
	if (sh != null)
	{
		fEncoded = false;
		if (typeof sh == 'string')
			szHeader = sh;
		else if (typeof sh != 'object')
			szHeader = "";
		else if (sh.xml != null)
			szHeader = sh.xml;
		else if (ht.length != 0)
		{
			if (sh.length == null)
			{
				var he = ht[0].type;
				if (he.elem != null)
				{
					he = GetSchema(this.oS, he).elems[he.elem];
				}
				szHeader=EncodeVar(this.oS, true, sh, he);
			}
			else
			{
				for (var i = 0; i < ht.length; i++)
				{
					if (sh[i] == null)
					{
						if (ht[i].fRequired)
							return ReportError( "Error - " + oCall + ", 9" );
						continue;
					}
					var he = ht[i].type;
					if (he.elem != null)
					{
						he = GetSchema(this.oS, he).elems[he.elem];
					}
					szHeader += EncodeVar(this.oS, true, sh[i], he);
				}
			}
			fEncoded = !ht[0].fLiteral;
		}
		szHeader = '<SOAP-ENV:Header xmlns="'
		+ (fEncoded ? '' : this.oS.targetns ) + '">\n'
		+ szHeader + "\n</SOAP-ENV:Header>\n";
	}
	//alert('part 5');
	// BREAKING ON BUTTON PRESS IN MOZILLA AFTER ALERT 5.
	var szPayload = "<?xml version='1.0'?>\n"
	+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="'
	+ oM.es + '" ' + sNS + ">\n"
	+ szHeader
	+ '<SOAP-ENV:Body>'
	+ szParams + "\n</SOAP-ENV:Body>\n"
	+ "</SOAP-ENV:Envelope>\n";
	
	//alert( szPayload );
	var r = null;
	
	//alert(_CONSTANT_OLDSCHOOL_IEXPLORER);
	if ( (this.Async == true) && (_CONSTANT_OLDSCHOOL_IEXPLORER == false) )
	{
		//alert('Sending this to the webservice:\n'+szPayload);
		xmlHttp.send(szPayload);
		
		var theService = this; // for the anonymous function
		
		xmlHttp.onreadystatechange=function() 
		{ 
			if (xmlHttp.readyState==4)
			{ 
				var response = xmlHttp.responseText;
			
				//alert('YO: '+response);
						
				var shrunk = xmlHttp.responseText.slice( (xmlHttp.responseText.indexOf(">")+1) ,xmlHttp.responseText.length );
				
				if ( _CONSTANT_MOZILLA == true ) 
				{
					try {
						xmlHttp.responseXML.loadXML( shrunk );
					}
					catch (e) 
					{}
				}
				
				if (xmlHttp.responseXML.parseError.errorCode != 0 && _CONSTANT_IEXPLORER == true || xmlHttp.responseXML.documentElement == null)
				{
					try
					{
						oCall.asynchandler(r);
					}
					catch(e)
					{}
				}			
					
				try
				{	
					//alert(oCall+'||'+xmlHttp.responseXML.documentElement+'||'+this);
					r = theService.ProcessResult(oCall, xmlHttp.responseXML.documentElement);
				}
				catch (e)
				{
					//alert('ProcessResult FAILED for async'+e);
					//return returnError(oCall, 7);
					try
					{
						oCall.asynchandler(r);
					}
					catch(e)
					{}
				}
					
				if ( oCall.asynchandler )
				{
					try
					{
						oCall.asynchandler(r);
					}
					catch( e )
					{
						//alert('EXCEPTION::' + e );
					}
					//	alert('tried to call our async handeling method');
				
					//var st = oCall.asynchandler.toString();
					//if ( typeof(eval(st)) == "function")
					//{
					//	eval(st+'(r)');
					//}
				}
			}
		};

		return "async";
	}
	else
	{
		try
		{
			r = xmlHttp.send(szPayload);
			//alert(r);
		}
		catch (e)
		{
			//return returnError(oCall, 5);
			return "Error 5";
		}
		
		// Wait a sec, i think both browsers do this... YES! SHOOT, not so... urg
		// PROBLEM WITH ASYNCRONUS CALLS, they need stuff immediatley.
				
		var shrunk = xmlHttp.responseText.slice( (xmlHttp.responseText.indexOf(">")+1) ,xmlHttp.responseText.length );
		//alert('responseText: '+xmlHttp.responseText.slice(2000,xmlHttp.responseText.length ));
		
		if ( _CONSTANT_MOZILLA == true ) {
			try {
				// Mozilla only has a text version, and as such does not have an xml tree
				// to parse.  SOOOO, we do the following, to give it that tree.
				//alert('before loadXML\n' + shrunk);
				xmlHttp.responseXML.loadXML( shrunk );
				//alert( 'name: ' + xml.nodeName +', text: '+ xml.text +', nodeTypedValue: '+ xml.nodeTypedValue +',\r\n name: '+ xml.firstChild.nodeName +', text: '+ xml.firstChild.text +', nodeTypedValue: '+ xml.firstChild.nodeTypedValue +',\r\n name: '+ xml.firstChild.firstChild.nodeName +', text: '+ xml.firstChild.firstChild.text +', nodeTypedValue: '+ xml.firstChild.firstChild.nodeTypedValue +',\r\n name: '+ xml.firstChild.firstChild.firstChild.nodeName +', text: '+ xml.firstChild.firstChild.firstChild.text +',\r\n name: '+ xml.firstChild.firstChild.firstChild.firstChild.nodeName +', text: '+ xml.firstChild.firstChild.firstChild.firstChild.text +', nodeValue: '+ xml.firstChild.firstChild.firstChild.firstChild.nodeValue +', nodeType: '+ xml.firstChild.firstChild.firstChild.firstChild.nodeType +', nodeTypedValue: '+ xml.firstChild.firstChild.firstChild.firstChild.nodeTypedValue +',\r\n name: '+ xml.firstChild.firstChild.firstChild.firstChild.firstChild.nodeName + ', text: '+ xml.firstChild.firstChild.firstChild.firstChild.firstChild.nodeValue +'.');   
			}
			catch (e) {
				//alert(e.message);
			}
		}
		
		if (xmlHttp.responseXML.parseError.errorCode != 0 && _CONSTANT_IEXPLORER == true)
		{
			// The error code is undefined for no good reason.  that
			// means it is not being set. lame.
			//alert('error code is:' + xmlHttp.responseXML.parseError.errorCode);
			
			//_errUnknownS.raw = sXmlHttp.responseText;
			//return returnError(oCall, 4);
			return "Error 4";
		}
		//alert('present');
		
		var sXmlHttpDoc = xmlHttp.responseXML.documentElement;
		
		if (sXmlHttpDoc == null)
		{
			//return returnError(oCall, 4);
			return "Error 4";
		}
		
		try
		{
			r = this.ProcessResult(oCall, sXmlHttpDoc, this);			
			//alert('r set good');
		}
		catch (e)
		{
			//return returnError(oCall, 7);
			return "Error 7";
		}		
		return r;
	}
};

WebServiceManager.prototype.ParseWsdl = function ()//function ParseWsdl( theService )
{
	//alert('BEGIN ParseWsdl FUNCTION ->' + theService.xd);  //ALERT!!! //WORKS
	wsdl = this.XmlDoc.documentElement; //theService.xd.documentElement;
	//alert( 'wsdl (if null, make sure webservice is running): '+((wsdl==null)? 'NULL' : 'GOOD') );
	if( wsdl == null )
		return;
	// Apply namespace schema from wsdl to XmlDoc
	NextITXD.setXpathNamespaces( this.XmlDoc, this.GetNamespaces( wsdl ) );//_service.xd, GetNamespaces( wsdl ) );

	//alert(wsdl.xml.toString().slice(8000,wsdl.xml.toString().length));
	//alert('done setting xpath namespaces');
	// so nsq sets up things.  But if it fails to set up service nodes, getting
	// the [0] service will still fail.  Suss this bad boy out!
	// and why does it only matter on the live site???  makes no sense...
	//alert('wsdl.nodeName: '+wsdl.nodeName);
	// nsq is the nodename with the ':' at the end (ex: 'wsdl:')
	var nsq = GetQualifier(wsdl.nodeName);
	nsq = nsq.length == 0 ? "" : (nsq + ":");
	if ( nsq == "" )
	{
		//alert('your headers are not set properley in the following xml file:\n'+wsdl.xml);
	}
	
	//var nMsgs = wsdl.selectNodes( "message" );
	var nMsgs	= wsdl.selectNodes(nsq + "message");
	var nPort	= wsdl.selectNodes(nsq + "portType");
	var nBinding = wsdl.selectNodes(nsq + "binding");
	var nService = wsdl.selectNodes(nsq + "service");
	var nTypes	= wsdl.selectNodes(nsq + "types");
		
	// starting here, we need to basically go through and make sure things are
	// set up properley.  Each for loop, if or anything else that relies on stuff
	// will need to be identified and accordingly set.
	
	var aMsgs    = new Array();
	var aPort    = new Array();
	var aBinding = new Array();
	
	var oS = new Object();
	oS.targetns = GetAttrib(wsdl, "targetNamespace");
	oS.ns = new Array();
	oS.ns[""] = "";
	oS.ns["xsd"] = "http://www.w3.org/2001/XMLSchema";
	oS.ns["soapenc"] = "http://schemas.xmlsoap.org/soap/encoding/";
	oS.ns["SOAP-ENV"] = 'http://schemas.xmlsoap.org/soap/envelope/';
	oS.schemas = new Array();
	oS.nsalias = new Array();
	oS.msgs = aMsgs;
	oS.refs = new Array();
	
	//build the namespace info
	for (var i = 0; i < wsdl.attributes.length; i++)
	{
		var oAtt = wsdl.attributes.item(i);
		if (oAtt.name == "xmlns")
		{
			continue;
		}
		var ii = oAtt.name.indexOf("xmlns:");
		if (ii != 0)
		{
			continue;
		}
		var nsn = oAtt.name.substring(6, oAtt.name.length);
	
		oS.ns[nsn] = oAtt.value;
		oS.nsalias[oAtt.value] = nsn;
		
	}
	//alert('namespace info built.');
	
	if (oS.ns["xsi"] == null)
		oS.ns["xsi"] = oS.ns["xsd"] == xsd99 ? xsi99 : xsi01;
	
	//Build The Types Info
	for (var i = 0; i < nTypes.length; i ++)
	{
		var nSchemas = nTypes[i].childNodes;
		// Appears as though the object is nothing in IE, but somthing in Moz.
		// also, the lengtth is 1 in IE, 3 in Moz.  NOT GOOD!
		// CND_1 Solved issue.
		//alert(i+' inner_i: '+nSchemas.length);  //ALERT!!! // NOT THE SAME
		for (var j = 0; j < nSchemas.length; j ++)
		{
			// This is called: Chases New Dependancy One, aka: CND_1
			// If there is no target namespace, it is simply not going
			// to work, and is most likley just a dummy place holder
			// that Moz DOM uses.  Best to ignore them.
			if (GetAttrib(nSchemas[j], "targetNamespace") != null)
			{
				var oSchm = new Object();
				
				oSchm.uri = GetAttrib(nSchemas[j], "targetNamespace");
				//alert(j+' inner_j: '+oSchm.uri);  //ALERT!!! CND_1 Solved issue.
				oSchm.efd = GetAttrib(nSchemas[j], "elementFormDefault");
				//alert(j+' inner_j: '+oSchm.efd);  //ALERT!!! CND_1 Solved issue.
				oSchm.afd = GetAttrib(nSchemas[j], "attributeFormDefault");
				//alert(j+' inner_j: '+oSchm.afd);  //ALERT!!! CND_1 Solved issue.
			
				//oSchm.service = szService;
				oSchm.elems = new Array();
				oSchm.types = new Array();
				oSchm.sTypes = new Array();
				oSchm.aTypes = new Array();
				var nElements = nSchemas[j].childNodes;
								
				// Lets make sure that the nElements are the same, cause if not,
				// this thing is gonna snap like a twig!
				// VALUEs not the same.  15 vrs 31 in test...
				//alert('childNodes length, inner_j: '+nElements.length);  //ALERT!!! // NOT THE SAME
				/*
				var stringer = "";
				for( var cn = 0; cn < nElements.length; cn++)
				{
					stringer += (cn+": \r\n");
					//stringer += (nElements[cn] + "\r\n");
					try
					{
						stringer += (nElements[cn].attributes.getNamedItem("name") + " -- ");
						stringer += (nElements[cn].attributes.getNamedItem("name").nodeName + " -- ");
						stringer += (nElements[cn].attributes.getNamedItem("name").nodeValue + " -- ");
						stringer += (nElements[cn].attributes.getNamedItem("name").nodeType + " -- \r\n");
					}
					catch (e){}
				}*/
				
				// detailed info of the situation.
				//alert(stringer);  //ALERT!!!
				
				for (var k = 0; k < nElements.length; k ++)
				{
					// This is called: Chases New Dependancy Two, aka: CND_2
					// If we are in Mozilla, the array of nodes has a dummy node
					// before and after each node with significant values.
					if( _CONSTANT_IEXPLORER == true )
					{
						//alert('ie'+k); //ALERT!!! //WORKS
						//alert(nElements[k].baseName) //ALERT!!! //WORKS
						var sn = GetAttrib(nElements[k], "name");
						if (sn == null)
							continue;
						switch(nElements[k].baseName)
						{
							case 'element' :
								//alert(k+': ParseElem-> '); //ALERT!!! //WORKS
								oSchm.elems[sn] = ParseElem(oS,oSchm,nElements[k],false,sn);
								break;
							case 'simpleType' :
							case 'complexType' :
								//alert(k+': ParseType-> '); //ALERT!!! //WORKS
								oSchm.types[sn] = ParseType(oS, oSchm, nElements[k]);
								break;
						}
					}
					
					if( _CONSTANT_MOZILLA == true && ((k%2)==1) )
					{
						//alert('mozilla'+(k-1)/2); //ALERT!!! //WORKS
						var sn = GetAttrib(nElements[k], "name");
						//alert(GetAttrib(nElements[k], "name")); //ALERT!!! 
						//alert(nElements[k].baseName); //ALERT!!! //FAILS, IE only!
						//alert(nElements[k].nodeName); //ALERT!!! //can work
						//alert(nElements[k].tagName); //ALERT!!! //can work
						
						// CHD_3.  baseName is IE only, so we need to make our own.
						var baseName_CR = ( nElements[k].nodeName.slice((nElements[k].nodeName.indexOf(":")+1),nElements[k].nodeName.length) );
						//alert(baseName_CR);  //ALERT!!! //WORKS
						if (sn == null)
							continue;
						switch(baseName_CR)
						{
							case 'element' :
								//alert(((k-1)/2)+': ParseElem-> '); //ALERT!!! //WORKS
								oSchm.elems[sn] = ParseElem(oS,oSchm,nElements[k],false,sn);
								break;
							case 'simpleType' :
							case 'complexType' :
								//alert(((k-1)/2)+': ParseType-> '); //ALERT!!! //WORKS
								oSchm.types[sn] = ParseType(oS, oSchm, nElements[k]);
								break;
						}
					}
				}
				oS.schemas[oSchm.uri] = oSchm;
				
				//  ALERT!!! //WORKS
				// This block is good for decting what has actually gone on in the
				// setting of elems array.
				/*
				var stringer = "";
				
				stringer += oSchm.elems.HelloWorld.name;
				stringer += " -- ";
				stringer += oSchm.elems.HelloWorld.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.HelloWorldResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.HelloWorldResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.Add.name;
				stringer += " -- ";
				stringer += oSchm.elems.Add.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.AddResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.AddResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.GetEvent.name;
				stringer += " -- ";
				stringer += oSchm.elems.GetEvent.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.GetEventResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.GetEventResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.MyEvent.name;
				stringer += " -- ";
				stringer += oSchm.elems.MyEvent.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.MyEventResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.MyEventResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.GetResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.GetResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.GetResponseResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.GetResponseResponse.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.CreateBrainID.name;
				stringer += " -- ";
				stringer += oSchm.elems.CreateBrainID.type;
				stringer += " \r\n";
				
				stringer += oSchm.elems.CreateBrainIDResponse.name;
				stringer += " -- ";
				stringer += oSchm.elems.CreateBrainIDResponse.type;
				stringer += " \r\n";
				*/
				/*
				var stringer = "";
				
				stringer += oSchm.types.HelloWorldResponse_HelloWorldResponse.HelloWorldResult.name;
				stringer += " -- ";
				stringer += oSchm.types.HelloWorldResponse_HelloWorldResponse.HelloWorldResult.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.AppCall.Name.name;
				stringer += " -- ";
				stringer += oSchm.types.AppCall.Name.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.AppCall.Value.name;
				stringer += " -- ";
				stringer += oSchm.types.AppCall.Value.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.ArrayOfAppCall.AppCall.name;
				stringer += " -- ";
				stringer += oSchm.types.ArrayOfAppCall.AppCall.type;
				stringer += " \r\n";
				//////////////////////////////BRAIN BELOW//////////////////////
				stringer += oSchm.types.BrainResponse.Response.name;
				stringer += " -- ";
				stringer += oSchm.types.BrainResponse.Response.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.BrainResponse.AppEvents.name;
				stringer += " -- ";
				stringer += oSchm.types.BrainResponse.AppEvents.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.BrainResponse.TextToSpeechPath.name;
				stringer += " -- ";
				stringer += oSchm.types.BrainResponse.TextToSpeechPath.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.BrainResponse.IsInImpasse.name;
				stringer += " -- ";
				stringer += oSchm.types.BrainResponse.IsInImpasse.type;
				stringer += " \r\n";
				
				stringer += oSchm.types.BrainResponse.DidYouMean.name;
				stringer += " -- ";
				stringer += oSchm.types.BrainResponse.DidYouMean.type;
				stringer += " \r\n";
				
				
				
				// detailed info of the situation.
				alert(stringer);  //ALERT!!!*/
				
			}//end chase's added if.
		}
	}
	//alert('type info info built.');
	
	for (var x in oS.refs)
	{
		//alert('we are in the oS.refs');
		var q = GetQualifier(x);
		var nsUri = oS.ns[q];
		var oschm = oS.schemas[nsUri];
		if (oschm == null)
			continue;
		var ot = oschm.elems[getBaseName(x)];
		oS.refs[x][ot.name] = ot;
	}
	//alert('oS.refs built.');
	
	//Message Nodes
	for (var i = 0; i < nMsgs.length; i++)
	{
		//alert('we are in the nMsgs:'+i);  //ALERT!!! //WORKIN
		var sName = GetAttrib(nMsgs[i], 'name');
		aMsgs[sName] = new Object();
		var ps = nMsgs[i].selectNodes(nsq + "part");
		aMsgs[sName].args = new Array();
		for (var j = 0; j < ps.length; j ++)
		{
			//alert('we are in the nMsgs sub:'+j);  //ALERT!!! //WORKIN
			var ap = new Object();
			ap.name = GetAttrib(ps[j], "name");
			ap.type = GetAttrib(ps[j], "type");
			ap.elem = GetAttrib(ps[j], "element");
			if (ap.elem != null)
			{
				ap.ns = GetQualifier(ap.elem);
				ap.elem = GetBaseName(ap.elem);
			}
			if (ap.type != null)
			{
				ap.ns = GetQualifier(ap.type);
				ap.type = GetBaseName(ap.type);
			}
			if (ap.ns != null && ap.ns != '')
			{
				var nsuri = GetAttrib(ps[j],'xmlns:'+ap.ns);
				if (nsuri != null)
					oS.ns[ap.ns] = nsuri;
			}
			aMsgs[sName].args[ap.name] = ap;
		}
		aMsgs[sName].argl = ps.length;
	}
	// Messages seem to be building good in both browsers.
	//alert('message nodes built.');  // ALERT!!! //WORKIN
	/*
	var stringer = "";
				
	stringer += aMsgs.HelloWorldSoapIn.args.parameters.name;
	stringer += " -- ";
	stringer += aMsgs.HelloWorldSoapIn.args.parameters.elem;
	stringer += " -- ";
	stringer += aMsgs.HelloWorldSoapIn.args.parameters.ns;
	stringer += " \r\n";
	
	stringer += aMsgs.HelloWorldSoapOut.args.parameters.name;
	stringer += " -- ";
	stringer += aMsgs.HelloWorldSoapOut.args.parameters.elem;
	stringer += " -- ";
	stringer += aMsgs.HelloWorldSoapOut.args.parameters.ns;
	stringer += " \r\n";
	
	stringer += aMsgs.CreateBrainIDSoapIn.args.parameters.name;
	stringer += " -- ";
	stringer += aMsgs.CreateBrainIDSoapIn.args.parameters.elem;
	stringer += " -- ";
	stringer += aMsgs.CreateBrainIDSoapIn.args.parameters.ns;
	stringer += " \r\n";
	
	stringer += aMsgs.CreateBrainIDSoapOut.args.parameters.name;
	stringer += " -- ";
	stringer += aMsgs.CreateBrainIDSoapOut.args.parameters.elem;
	stringer += " -- ";
	stringer += aMsgs.CreateBrainIDSoapOut.args.parameters.ns;
	stringer += " \r\n";
	
	// detailed info of the situation.
	alert(stringer);  //ALERT!!! //WORKIN*/
	
	//Build PortType Info
	for (var i = 0; i < nPort.length; i++)
	{
		var sName = GetAttrib(nPort[i], "name");
		aPort[sName] = new Object();
		var nops = nPort[i].selectNodes(nsq + "operation");
		var oops = new Array();
		aPort[sName].ops = oops;
		for (var j = 0; j < nops.length; j++)
		{
			var sOpName = GetAttrib(nops[j], "name");
			var nInputs = nops[j].selectNodes(nsq + "input");
			var mInput = null;
			if (nInputs.length > 0)
			{
				var s = GetAttrib(nInputs[0], "message");
				var sMsgName = GetBaseName(s);
				var sNS = GetQualifier(s);
				if (oops[sOpName] == null)
					oops[sOpName] = new Array();
				var sin = GetAttrib(nInputs[0], "name");
				if (sin != null)
					oops[sOpName][sin] = aMsgs[sMsgName];
				else
					oops[sOpName][sOpName] = aMsgs[sMsgName];
				if (aMsgs[sMsgName] == null)
					break;
				aMsgs[sMsgName].opname = sOpName;
				mInput = aMsgs[sMsgName];
			}
			var nOutputs = nops[j].selectNodes(nsq + "output");
			if (nOutputs.length > 0)
			{
				var s = GetAttrib(nOutputs[0], "message");
				var sMsgName = GetBaseName(s);
				var sSoapName = aMsgs[sMsgName].soapName;
				if (sSoapName == null)
					aPort[sName].ops[sMsgName] = aMsgs[sMsgName];
				else
				{
					aPort[sName].ops[sSoapName] = aMsgs[sMsgName];
					aMsgs[sSoapName] = aMsgs[sMsgName];
				}
				if (mInput != null)
					mInput.response = aMsgs[sMsgName];
			}
		}
	}
	//alert('port types built.');
	/*
	var stringer = "";
				
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.args.parameters.name;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.args.parameters.type;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.args.parameters.elem;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.args.parameters.ns;
	stringer += " \r\n";
	
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.response.args.parameters.name;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.response.args.parameters.type;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.response.args.parameters.elem;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainID.CreateBrainID.response.args.parameters.ns;
	stringer += " \r\n";
	
	stringer += aPort.MyServiceSoap.ops.CreateBrainIDSoapOut.args.parameters.name;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainIDSoapOut.args.parameters.type;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainIDSoapOut.args.parameters.elem;
	stringer += " -- ";
	stringer += aPort.MyServiceSoap.ops.CreateBrainIDSoapOut.args.parameters.ns;
	stringer += " \r\n";
	
	// detailed info of the situation.
	alert(stringer);  //ALERT!!! //WORKIN*/
	
	var soap = 'soap';
		
	//build binding object array
	for (var i = 0; i < nBinding.length; i++)
	{
		var osoapb = '';
		try {
			osoapb = nBinding[i].selectNodes(soap+":binding");
		} catch(e) {
			soap = 'wsdlsoap'; // Java webservices use this prefix
			osoapb = nBinding[i].selectNodes(soap+":binding");
		}
		
		if (osoapb == null || osoapb.length == 0)
			continue;
		var sStyle= GetAttrib(osoapb[0], "style");
		var sName = GetAttrib(nBinding[i], "name");
		aBinding[sName] = new Object();
		var stype = GetBaseName(GetAttrib(nBinding[i], "type"));
		aBinding[sName].msgs = aPort[stype].ops;
		var nops = nBinding[i].selectNodes(nsq + "operation");
		for (var j = 0; j < nops.length; j++)
		{
			var sOpName = GetAttrib(nops[j], "name");
			var input = nops[j].selectSingleNode(nsq + "input");
			if (input == null)
				continue;
			var sin = GetAttrib(input, "name");
			if (sin == null)
				sin = sOpName;
			var oM = aBinding[sName].msgs[sOpName][sin];
			if (oM == null)
				continue;
			var nsoapops = nops[j].selectNodes(soap+":operation");
			if (nsoapops.length == 0)
				continue;
			var sOpStyle= GetAttrib(nsoapops[0], "style");
			oM.soapAction = GetAttrib(nsoapops[0], "soapAction");
			var nsoapbody = nops[j].selectNodes(nsq + "input/"+soap+":body");
			if (nsoapbody.length > 0)
			{
				oM.ns = GetAttrib(nsoapbody[0], "namespace");
				oM.es = GetAttrib(nsoapbody[0], "encodingStyle");
				var sUs = GetAttrib(nsoapbody[0], "use");
				oM.fLiteral = (sUs != null && sUs.toLowerCase() == 'literal');
			}
			var nsoaphead = nops[j].selectNodes(nsq + "input/"+soap+":header");
			oM.headers = new Array();
			for (var k = 0; k < nsoaphead.length; k ++)
				oM.headers[k] = ParseSoapHeader(oS, nsoaphead[k]);
			if (sOpStyle != null)
				oM.fRpc = sOpStyle.toLowerCase()=='rpc';
			else
				oM.fRpc=(sStyle !=null && sStyle.toLowerCase()=='rpc');
		}
	}
	//alert('nBindings built.');
	
	//Ports
	var nports = nService[0].selectNodes(nsq + "port");
	oS.soapPort = new Array();
	for (var j = 0; j < nports.length; j++)
	{
		var oAddress = nports[j].selectNodes(soap+":address");
		if (oAddress.length == 0)
			continue;
		var oSOAPHdr = nports[j].selectNodes(soap+":header");
		oS.headers = new Array();
		for (var k = 0; k < oSOAPHdr.length; k ++)
			oS.headers[k] = ParseSoapHeader(oS, oSOAPHdr[k]);
		oPort = new Object();
		oPort.location = GetAttrib(oAddress[0], "location");
		var b = aBinding[GetBaseName(GetAttrib(nports[j], "binding"))];
		oPort.msgs = b.msgs;
		var szname = GetAttrib(nports[j], "name");
		oS.soapPort[szname] = oPort;
		if (oS.defPortName == null)
			oS.defPortName = szname;
	}
	//alert('nPorts built.');
		
	//attach all the arrays to the main object
	this.Messages = aMsgs;
	this.Ports = aPort;
	this.Bindings = aBinding;
	this.oS = oS;
	
	// Call event if available	
	if( this.OnWsdlParsed != null )
	{
		this.OnWsdlParsed();
	}
	
	//alert('ALL DONE with this function.');
};

WebServiceManager.prototype.ProcessResult = function(oC, oResult)
{
	var r = new Object();
	r.id = oC.id;
	if (oResult == null)
	{
		r.error = true;
		//r.errorDetail = _errUnknownS;
		return ReturnResult(oC, r);
	}
	try
	{
		var pf = oResult.prefix;
	}
	catch (e)
	{
		pf = null;
	}
	//pf is basically "soap"
	var ns = pf == null ? "" : (pf + ":");
	if ( ns == "") // for Mozilla
	{
		ns = "soap:";
	}
	//alert('ns: '+ns+ "Body");
	//ns is basically "soap:"
	var oBody = oResult.selectSingleNode(ns + "Body");
	//alert('body: '+oBody);
	//oBody is basically NODE<soap:Body>	
	
	////////////////////////////////////////////////////////////////////////////////
	// This block is just error section, nothing more.
	if (oBody == null)
	{
		r.error = true;
		r.errorDetail = _errInvalRes;
		return ReturnResult(oC, r);
	}
	var aryFault = oBody.selectNodes(ns + "Fault");
	if (aryFault.length > 0)
	{
		r.error = true;
		r.errorDetail = new Object();
		var ac = aryFault[0].selectNodes(ns+"faultcode");
		if (ac.length == 0)
			ac = aryFault[0].selectNodes("faultcode");
		r.errorDetail.code=ac.length > 0 ? ac[0].firstChild.nodeValue:"Unknown";
		var as = aryFault[0].selectNodes(ns+"faultstring");
		if (as.length == 0)
			as = aryFault[0].selectNodes("faultstring");
		if (as.length > 0 && as[0].hasChildNodes())
			r.errorDetail.string= as[0].firstChild.nodeValue;
		else
			r.errorDetail.string= "";
		r.errorDetail.raw = oResult;
		alert('Error from the webservice:\n'+r.errorDetail.string);
		return ReturnResult(oC, r);
	}
	r.error = false;
	r.raw   = oResult;
	// end error detection block
	////////////////////////////////////////////////////////////////////////////////
	
	// if it has no child nodes, return it real quick like!
	if (!oBody.hasChildNodes())
	{
		r.value = null;
		return ReturnResult(oC, r);
	}
	
	// if the oS of the doc is null, return it real quick like!
	var oS = this.oS;
	if (oS == null || oS.fPending)
	{
		r.error = true;
		r.errorDetail = _errNotReady;
		return ReturnResult(oC, r);
	}
	
	// Lets grab first child of NODE<soap:Body>
	var o = oBody.firstChild;	
	
	// get the baseName.  needs to change for Mozilla.
	var szResName = o.nodeName.slice((o.nodeName.indexOf(":")+1),o.nodeName.length);
	
	// that huge node structure we built on the page load.
	var oschm = oS.schemas[o.namespaceURI];
	
	var args = null;
	
	// seems to be null for now.
	var oM = oC.fRpc ? oC.response : null;
	
	if (oM)
	{
		args = oM.args;
	}
	// since oM = null always as far as i can tell, this is the loop.
	else
	{
		// oM is no longer null, but the message for this portName
		oM = oS.soapPort[oC.portName].msgs[szResName];
		// Always gonna happen.
		if (oM == null)
		{
			var el = oschm == null ? null : oschm.elems[szResName];
			if (el == null)
			{
				if (!oC.fLiteral && oschm != null)
				{
					args = oschm.types[szResName];
				}
				if (args == null)
					args = oC.response.args;
				if (args == null)
				{
					r.error = true;
					r.errorDetail = _errInvalRes;
					return ReturnResult(oC, r);
				}
			}
			else if (el.fFinal)
				args = el;
			else // Always gonnaa happen.
				args = oschm.types[el.type];
		}
		else
		{
			// args = to the args of oM
			args = oM.args;
		}
	}
	// not likely
	if (args == null)
	{
		r.value = null;
		return ReturnResult(oC, r);
	}
	
	var l = 0;
	// l=0 is not possible
	for (var i in args)
		l++;	//what is l?
	if (l == 0)
	{
		r.value = null;
	}
	else //this loop always
	{
		if (args.type != null)
		{
			l = 1; //l is 1 now...
		}
		// could be difficult to emulate, but it returns a piece of the 
		// node tree.
		
		// No double lines, obfuscation error if you do so.
		var nodeSelectionString = "/*[@id]";
		nodeSelectionString = "/" + nodeSelectionString;
		
		var aryNwId = o.selectNodes(nodeSelectionString);
		var aNodes = new Array();
		for (var i = 0; i < aryNwId.length; i++) // never hits this loop
		{
			aNodes[GetAttrib(aryNwId[i], "id")] = aryNwId[i];
		}
		// if we can pass into this DecodeType method a 'fake' copy, via
		//  a home made datastructure, we might just get away with it...
		var ar = DecodeType(oS, args, o, aNodes); // actually gets the object, does about 90% of the work.
		if (l == 1) // seems a bit unessasary.
		{
			for (var i in ar) 
			{
				r.value = ar[i];
				break;
			}
		}
		else
			r.value = ar;
	}	
	return ReturnResult(oC, r); // returns the result object, aka r.
};
function ReturnResult(oCall, r)
{
	if (oCall.cb)
	{
		try 
		{ 
			oCall.cb(r); 
		} 
		catch (e) 
		{};
	}

	if (oCall.async == false)
	{
		return r;
	}
	if (oCall.cb == null)
	{	
		r.error = true;
		r.errorDetail = new ErrDetail("Client", "No Callback provided",	null);
		return r;
	}
};
WebServiceManager.prototype.GetNamespaces = function( xml )
{
	this.NameSpaces = new Array();
	var reg = /xmlns\:/;
	for( var i = 0; i < xml.attributes.length; i++ )
	{
		if( xml.attributes[i].nodeName.match( reg ) )
		{
			var nameSpace = new Object();
			//alert('nodeName sub '+i+' ->'+xml.attributes[i].nodeName+'\r\nnodeValue sub '+i+' ->'+xml.attributes[i].nodeValue);
			nameSpace.NSName = xml.attributes[i].nodeName;
			nameSpace.NSValue = xml.attributes[i].nodeValue;
			try
			{
				this.NameSpaces.push( nameSpace );
			}
			catch(e)
			{
				try
				{
					this.NameSpaces[_service.NameSpaces.length] = nameSpace;
					this.NameSpaces.length++;
				}
				catch(e)
				{
					alert('push on array failed in GetNamespaces');
				}
			}
		}
	}
	
	if( this.NameSpaces.length > 0 )
	{
		return BuildNamespaceStringForXD( this.NameSpaces );
	}
	else
		return "";
};

function BuildNamespaceStringForXD( ns )
{
	var str = "";
	//alert(ns.length);
	for( var i = 0; i < ns.length; i++ )
	{
		try
		{
			str += ns[i].NSName + "='" + ns[i].NSValue + "' ";
		}
		catch(e)
		{
			//alert(i);
		}
	}
	
	str = str.substring( 0, ( str.length - 1 ) );
	return str;
};

function GetQualifier(str)
{
	var a = str.split(":");
	if (a.length > 1)
		return a[0];
	return '';
};

function GetAttrib(xml, sAName)
{
	//alert('hi, im get attributes.');
	try
	{
		var a = xml.attributes.getNamedItem(sAName);
		//alert('got attrib '+ sAName +': '+ a);
		
	}
	catch(e)
	{
		a = null; //alert('NO attrib'); 
	}
	//alert(a);
	if (a != null)
		return a.value;
	return null;
};

function ParseElem(oS, oschm, o, fNested, ssffx)
{
	var oe = new Object();
	oe.name = GetAttrib(o, "name"); 
	// Lets focus on this one for now.  why is the type failing?
	// maybe we are passing it a bad value...
	var st = GetAttrib(o, "type"); 
	//alert('st: '+st);   //ALERT!!! 
	var minOccurs = GetAttrib(o, "minOccurs");
	var maxOccurs = GetAttrib(o, "maxOccurs");
	oe.fArray = (maxOccurs != null && maxOccurs != "1");
	if (st != null)
	{
		oe.type = GetBaseName(st);
		oe.ns = GetQualifier(st);
		oe.fFinal = true;
		return oe;
	}
	oe.fFinal = false;
	// THE TRUTH!!! passing o.firstChild seems to fail...  Because the node
	// is a text node, and hence does not have the correct properties..
	//alert('number of child nodes: ' + o.childNodes.length + ':: ' + o.childNodes[1].nodeName);
	if( _CONSTANT_MOZILLA == true )
	{
		// alert(o.childNodes.length);
		// okay, this is officialy the case.  Mozilla surrounds every instance of a node
		// collection object with a dummy node before and after it, in such a way
		// that n nodes in IE become 2n+1 in mozilla (dummy nodes overlap).
		// this is most likely going to cause problems throughout.
		try
		{
			var ct = ParseType(oS, oschm, o.childNodes[1], oe.name); ////PARSE_TYPE////
		}
		catch(e){}
	}
	else
	{
		var ct = ParseType(oS, oschm, o.firstChild, oe.name); ////PARSE_TYPE////
	}
	//alert('ct: '+ct);   //ALERT!!! //WORKS
	if (fNested && ct != null)
	{
		var k = null;
		for (var j in ct)
		{
			if (k == null)
				k = j;
			else
			{
				k = null; break;
			}
		}
		if (k != null)
		{
			oe.type = ct[k].type;
			oe.ns = ct[k].ns;
			oe.fArray = ct[k].fArray;
			oe.fNested = true;
			return oe;
		}
	}
	if (typeof ssffx != 'undefined')
		oe.type = ssffx + '_' + oe.name;
	else
		oe.type = oe.name;
	oschm.types[oe.type] = ct;
	return oe;
};

function ParseType(oS, oschm, o, ssffx)
{
	//alert('HIIIIII-'+o.nodeName+'-'+o.nodeType+'-'+o.tagName);  //ALERT!!! //WORKIN
	if (o == null)
		return null;
	switch( o.nodeName.slice((o.nodeName.indexOf(":")+1),o.nodeName.length) )
	{
		case "complexType" :
			return ParseComplexType(oS, oschm, o, ssffx);
		case "simpleType" :
			return ParseSimpleType(oS, oschm, o, ssffx);
	}
	return null;
};

function ParseAttrib(o)
{
	var attrib = new Object();
	attrib.fAttrib = true;
	attrib.type = GetAttrib(o, "type");
	return attrib;
};

function ParseComplexType(oS, oschm, o, ssffx)
{
	//alert('complex ->'+o.nodeName);  //ALERT!!! //WORKIN
	var ns = GetQualifier(o.nodeName); // not working, which causes NSBAD to fail.
	if (!o.hasChildNodes())
		return null;
	var ot = null;
	
	for (var j = 0; j < o.childNodes.length; j++)
	{
		// Once again, we need to make sure the node structure
		// ignores the dummy nodes of mozilla.
		var o1 = null;
		if ( _CONSTANT_IEXPLORER == true )
		{
			o1 = o.childNodes[j];
			
			
		}
		if( _CONSTANT_MOZILLA == true && ((j%2)==1) )
		{	
			try
			{
				o1 = o.childNodes[j];
			}
			catch(e)
			{
				o2 = o1.firstChild;
			}
		}

		// Ok, we still have a null going on here, so either pass in a value that does nothing
		// but continue the loop, or break out before bad things happen.
		if ( o1 == null )
		{
			o1 = o.childNodes[j];
			if ( j+1 == o.childNodes.length)
			{
				break;
			}
		}
		
		switch(o1.nodeName.slice((o1.nodeName.indexOf(":")+1),o1.nodeName.length))
		{
			case 'sequence' :
			case 'all' :
				//alert('all');
				// This case gets called 100% of the time as far as i can tell.
				//var ao = o1.selectNodes(ns.length ? (ns+':any') : 'any');
				//if (ao.length != 0)
				//	continue;
				//alert('1 '+ns); // NSBAD failing right here!!! ns = 's' as far as i can tell.
				var ao = o1.selectNodes(ns.length ? (ns+':element') : 'element');
				//alert('2-'+ao.length);
				//if (ao.length == 0)
				//{
				//	continue;
				//}
				//alert('3'+ao);
				ot = new Array();
				//alert('4');
				for (var i = 0; i < ao.length; i++)
				{
					//alert('i sub:'+i);
					var s = GetAttrib(ao[i], "name");
					//alert('ao ->' + s);
					if (s == null)
					{
						var s = GetAttrib(ao[i], "ref");
						if (s != null)
						{
							oS.refs[s] = ot;
						}
					}
					else
						ot[s] = ParseElem(oS, oschm, ao[i], true, ssffx); ////PARSE_ELEM////
				}
				continue;
			case 'complexContent' :
				var o2 = null;
				// Need to fix er up for mozilla, dummy nodes again.
				if( _CONSTANT_MOZILLA == true )
				{
					try
					{
						o2 = o1.childNodes[1];
					}
					catch(e)
					{
						o2 = o1.firstChild;
					}
				}
				else
				{
					o2 = o1.firstChild;
				}
				switch(o2.nodeName.slice((o2.nodeName.indexOf(":")+1),o2.nodeName.length))
				{
					case 'restriction' :
						var tn = GetAttrib(o, "name");
						if (tn == null)
							continue;
						tn = GetBaseName(tn);
						var tt =  ParseComplexType(oS, oschm, o2, ssffx); ////PARSE_COMPLEXTYPE////
						oschm.aTypes[tn] = tt;
						return tt;
					case 'all' :
						return ParseComplexType(oS, oschm, o1, ssffx); ////PARSE_COMPLEXTYPE////
				}
				continue;
			case 'attribute' :
				var arrayType = GetAttribEx(o1, "arrayType");
				if (arrayType == null)
				{
					if (ot == null)
					ot = new Array();
					ot[GetAttrib(o1, "name")] = ParseAttrib(o1);
					continue;
				}
				var tn = GetBaseName(arrayType);
				if (ot != null)
				{
					var oe = get1stAryItem(ot);
					oe.fArray = true;
					oe.fNested = true;
					oe.sizeArray = new Array();
					ParseArrayType(oe.sizeArray,
					tn.substring(tn.indexOf("[")+1, tn.length));
					continue;
				}
				var oe = new Object();
				var a = tn.split("[");
				if (a.length < 2)
					continue;
				oe.ns = GetQualifier(arrayType);
				oe.name = a[0];
				oe.fArray = true;
				oe.type = a[0];
				oe.sizeArray = new Array();
				oe.fNested = true;
				ParseArrayType(oe.sizeArray,
				tn.substring(tn.indexOf("[")+1, tn.length));
				ot = new Array();
				ot[a[0]] = oe;
				continue;
			default:
				ot = null;
		}
	}
	return ot;
};

function ParseSimpleType(oS, oschm, o, ssffx)
{
	//alert('simple'+o.length);  //ALERT!!! //WORKS
	var ns = GetQualifier(o.tagName);
	var o1 = o.firstChild;
	if (o1 == null)
		return null;
	var sn = GetAttrib(o, "name");
	if (sn == null)
		return null;
	sn = GetBaseName(sn);
	var ot;
	switch(o1.nodeName.slice((o1.nodeName.indexOf(":")+1),o1.nodeName.length))
	{
		case 'restriction' :
			var ao = o1.selectNodes(ns.length?(ns + ':enumeration'):'enumeration');
			if (ao.length == 0)
				return null;
			ot = new Object();
			ot.name = sn;
			ot.type = 'enum';
			try
			{
				ot.base = GetBaseName(getAttrib(o1, "base"));
			}
			catch (e)
			{
				ot.base = "string";
			}
			oschm.sTypes[sn] = ot;
			break;
		default:
			ot = null;
	}
	return ot;
};

function GetBaseName(str)
{
	//alert('GetBaseName says: ' + str);
	var a = str.split(":");
	if (a.length > 1)
		return a[1];
	return str;
};

function GetAttribEx(o, bn)
{
	var a = o.attributes;
	for (var i = 0; i < a.length; i++)
	{
		//alert('warning: baseName');
		if (a[i].baseName == bn)
		{
			return a[i].value;
		}
	}
	return null;
};

function ParseArrayType(at, sz)
{
	var asa = sz.split("[");
	if (asa.length <= 1)
	{
		asa = sz.split(",");
		for (var i = 0; i < asa.length; i++)
		{
			var ii = parseInt(asa[i]);
			at[at.length] = isNaN(ii) ? null : ii;
		}
		return;
	}
	for (var i=0; i < asa.length; i++)
		ParseArrayType(at, asa[i]);
};

function GetMsg(service, co, args)
{
	var oM;
	var mn = co.wsFuncName;
	var oS = service.oS;
	try
	{
		var sp = oS.soapPort[co.portName];
		oM  = sp.msgs[mn];
	}
	catch (e)
	{
		return null;
	}
	if (oM == null || oM.length == null)
	{
		return null;
	}
	var om1;
	for (om1 in oM)
	{
		if (oM[om1].args.length == args.length)
		{
			oM = oM[om1];
			break;
		}
	}
	if (oM.length != null)
		oM = oM[om1];
	return oM;
};

function EncodeArgs(oM, service, args, argIdx)
{
	//alert('encoding');
	var os = service.oS;
	var l = args.length;
	var sz = '';
	var mn = oM.opname;
	var fDocEnc = !oM.fRpc && !oM.fLiteral;
	//alert('1');
	
	if (!oM.fRpc && oM.argl == 1)
	{
		var pn = null;
		for (pn in oM.args)
			break;
		if (pn == null)
		{
			return null;
		}
		var a = oM.args[pn];
		if (!oM.fLiteral && a.type == null)
		{
			a.type = a.elem;
		}
		
		var et = a;
		if (a.elem != null)
		{
			var oschm = GetSchema(os, a);
			et = oschm == null ? a : oschm.elems[a.elem];
		}
		var qn = a.ns == null ? "" : (a.ns + ":");
		var nsd = ' xmlns ="'+(a.ns == null ? os.targetns : os.ns[a.ns]) + '"';
		
		if (oM.fLiteral && a.elem != null)
			sz += '\n<' + a.elem + nsd + '>';
		else
			sz += '\n<' +qn+a.type+' xmlns="" xsi:type="' + qn + a.type + '">';
		var i = argIdx;
		
		if (et.fFinal == true)
		{
			sz += EncodeVar(os, fDocEnc, args[i], et);
		}
		else
		{
			if (isPrimitive(os, et))
			{
				sz += '\n<' + et.type + '>';
				sz += EncodePrimitive(os, et.type, args[i]);
				sz += '</' + et.type + '>';
			}
			else
			{
				var oschm = GetSchema(os, et);
				if (oschm == null)
					return null;
				var tat = oschm.types[et.type];
				for (var tn in tat)
				{
					if (i >= l)
						break;
					sz += '\n<' + tat[tn].name + '>';
					sz += EncodeVar(os, fDocEnc, args[i], tat[tn]);
					sz += '</' + tat[tn].name + '>';
					i ++;
				}
			}
		}
		if (oM.fLiteral && a.elem != null)
		{
			sz += '</' + a.elem + '>';
		}
		else
		{
			sz += '</' + qn + a.type + '>';
		}
		return sz;
	}
	
	if (oM.fRpc)
	{
		sz =  "\n<mswsb:" + mn + GetNs(os, oM) + '>';
	}
	var i = argIdx;
	for (var pn in oM.args)
	{
		if (i >= l)
			break;
		var a = oM.args[pn];
		if (a.elem == null && a.type == null)
			return null;
		var pns = oM.fLiteral ? "mswsb:" : "";
		if (oM.fRpc)
		{
			var szt = '';
			if (a.type!=null && isPrimitive(os, a))
				szt = ' xsi:type="xsd:' + a.type + '"';
			var oschm = GetSchema(os, a);
			var ct = oschm == null ? null : oschm.types[a.type];
			var aryItem = null;
			if (ct != null)
			{
				aryItem = Get1stAryItem(ct);
				if (!aryItem.fArray)
					aryItem = null;
			}
			if (aryItem != null)
			{
				var as = aryItem.sizeArray;
				var k = 1;
				k = (as == null) ? 1 : as.length;
				var arr = args[i];
				//if (typeof arr == 'unknown')
					//arr = vbArrayToJs(arr, k);
				var sArr = GetArySize(arr);
				if (as != null)
				{
					sArr = "";
					for (var j = 0;;)
					{
						var l2 = GetArySize(arr);
						if (as[j] == null)
							sArr+=l2;
						else
							sArr+=Math.min(as[j], l2);
						j = j + 1;
						if (j == as.length)
							break;
						
						sArr += ",";
						if (l2 == 0)
							return null;
						arr = Get1stAryItem(arr);
					}
				}
				var oschm = GetSchema(os, aryItem);
				if (oschm != null)
					aryItem.ns = os.nsalias[oschm.uri];
				var ts = (isPrimitive(os, aryItem) || aryItem.ns == "")? "xsd:" : (aryItem.ns + ":");
				
				szt = ' xsi:type="soapenc:Array"' + ' soapenc:arrayType="'+ts+aryItem.type+'['+sArr+']"';
			}
			else
				szt = ' xsi:type="' + (a.ns == '' ? '' : (a.ns + ':'))+ a.type + '"';
			sz += '\n<' + pns +a.name+(oM.fLiteral?'':' xmlns=""')+szt+'>';
		}
		var et = (a.elem == null ? a : GetSchema(os, a).elems[a.elem]);
		if (oM.fLiteral)
		{
			if (a.elem != null)
				sz += '\n<' + a.elem + GetNs(os, oM) + '>';
			sz += EncodeVar(os, fDocEnc, args[i], et);
			if (a.elem != null)
				sz += '</' + a.elem + '>';
		}
		else
		{
			if (a.type == null)
				return null;
			if (oM.fRpc)
			{
				sz += EncodeVar(os, fDocEnc, args[i], et);
			}
			else
			{
				sz += '\n<' + a.type + '>' + EncodeVar(os, fDocEnc, args[i], et) + '</' + a.type + '>'
			}
		}
		if (oM.fRpc)
			sz += '</' + pns + a.name + '>';
		i ++;
	}
	if (oM.fRpc)
	{
		sz += "</mswsb:" + mn + ">";
	}
	return sz;
};

function GetNs(os, oM)
{
	var sNSMeth = oM.ns == null ? os.targetns : oM.ns;
	return ' xmlns' + (oM.fRpc ? ':mswsb' : '') + '="' + sNSMeth + '"';
};

function ReportError( err )
{
	//implement an error report service
};
function DecodeType(os, ot, o, aNodes)
{
	if (ot == null)
		return null;
	var oschm = null;
	var j = -1;
	var or = new Array();
	if (ot.type != null)
	{
		var st = ot.type;
		oschm = GetSchema(os, ot);
		if (isSimpleType(os, oschm, ot))
		{
			var stype = oschm == null ? null : oschm.sTypes[st];
			if (stype != null)
				st = stype.type;
			if (ot.fArray)
			{
				or["result"] = new Array();
				var o2 = o.childNodes;
				if (o2.length == 0)
					return or;
				var ai = ot.sizeArray;
				if (ai == null)
				{
					ai = new Array();
					ai[0] = o2.length;
				}
				if (ai.length == 1 && ai[0] == null)
					ai[0] = o2.length;
				var fnDec = function(vi) {return DecodePrimitive(os, st, vi)};
				DecodeArray(0, or["result"], ai, 1, o2, fnDec);
			}
			else
				or["result"] = DecodePrimitive(os, st, o);
			return or;
		}
		else
		{
			or["result"] = DecodeType(os, oschm.types[st],o,aNodes);
			return or;
		}
	}
	for (var sn in ot)
	{
		j++;
		var st = ot[sn].type;
		oschm = GetSchema(os, ot[sn]);
		if (st == null)
		{
			or[sn] = null;
			continue;
		}
		if (ot[sn].fAttrib == true)
		{
			var attrib = o.attributes.getNamedItem(sn);
			if (attrib != null)
			or[sn] = attrib.value;
			continue;
		}
		var o1s = o.selectNodes(sn);
		if (o1s.length == 0)
		{
			if (!o.hasChildNodes())
				o1 = o;
			else
			{
				o1 = null; // Don't confuse with last o1
				for (var i=0; i<o.childNodes.length; i++) // Try to find it manually (no more "j" guessing)
				{
					if (o.childNodes[i].tagName == sn)
					{
						o1 = o.childNodes[i];
						break;
					}
				}
				if (o1 == null) // try old method, just in case
					o1 = o.childNodes[j];
				if (o1 == null)
					continue;
			}
		}
		else
			o1 = o1s[0];
		if (!o1.hasChildNodes())
		{
			var sr = null;
			try 
			{
				sr = getAttrib(o1, "href");
			} 
			catch (e)
			{};
			if (sr != null && sr.charAt(0) == '#')
				o1 = aNodes[sr.substring(1, sr.length)];
			else if (isSimpleType(os, oschm, ot[sn]))
			{
				or[sn] = DecodePrimitive(os, st, o1);
				continue;
			}
		}
		if (isSimpleType(os, oschm, ot[sn]))
		{
			var stype = oschm == null ? null : oschm.sTypes[st];
			if (stype != null)
				st = stype.type;
			if (ot[sn].fArray)
			{
				var o2;
				var ai = GetArrayInfo(o1);
				var fNested = ot[sn].fNested == true || ai != null;
				if (fNested)
				{
					or[sn] = new Array();
					o2 = o1.childNodes;
				}
				else
					o2 = o.childNodes;
				if (o2.length == 0)
					return or;
				if (ai == null)
				{
					ai = ot[sn].sizeArray;
					if (ai == null)
					{
						ai = new Array();
						ai[0] = o2.length;
					}
				}
				if (ai.length == 1 && ai[0] == null)
					ai[0] = o2.length;
				var fnDec = function(vi) {return DecodePrimitive(os, st, vi)};
				DecodeArray(0,fNested?or[sn]:or,ai, 1, o2, fnDec);
			}
			else
				or[sn] = DecodePrimitive(os, st, o1);
			continue;
		}
		var ot1 = oschm.aTypes[st];
		var fCompArray = true;
		if (ot1 == null)
		{
			fCompArray = false;
			ot1 = oschm.types[st];
		}
		if (fCompArray)
		{
			return DecodeType(os, ot1, o, aNodes);
		}
		if (ot1 == null)
		{
			or[sn] = o1;
			continue;
		}
		if (ot[sn].fArray)
		{
			var ai = GetArrayInfo(o1);
			var fNested = ot[sn].fNested == true || ai != null;
			var o2 = fNested ? o1.childNodes : o.childNodes;
			if (ai == null)
			{
				ai = ot[sn].sizeArray;
				if (ai == null)
				{
					ai = new Array();
					ai[0] = o2.length;
				}
			}
			if (ai.length == 1 && ai[0] == null)
				ai[0] = o2.length;
			var fnDec = function(vi)
				{
				var sr = GetAttrib(vi, "href");
				if (sr != null && sr.charAt(0) == '#')
				vi = aNodes[sr.substring(1, sr.length)];
				return DecodeType(os, ot1, vi, aNodes);
				};
			if (fNested)
				or[sn] = new Array();
			DecodeArray(0,fNested?or[sn]:or,ai, 1, o2, fnDec);
		}
		else
		{
			or[sn] = DecodeType(os, ot1, o1, aNodes);
		}
	}
	return or;
};
function ErrDetail(errCode, errString, errRaw)
{
	this.code = errCode;
	this.string = errString;
	this.raw = errRaw;
};
function GetSchema(os, t)
{
	if (t.ns==null)
		return Get1stAryItem(os.schemas);
	var nsUrl = os.ns[t.ns];
	var oschm = os.schemas[nsUrl];
	if (oschm != null || t.ns.length == 0)
		return oschm;
	for (var x in os.schemas)
		if (x.indexOf(nsUrl) == 0 && os.schemas[x].types[t.type] != null)
			return os.schemas[x];
	return null;
};
function Get1stAryItem(a)
{
	for (var x in a)
		return a[x];
};
function isSimpleType(os, oschm, t)
{
	return isPrimitive(os, t) || oschm == null || oschm.sTypes[t.type]!=null;
};
function isPrimitive(os, t)
{
	return os.ns[t.ns] == os.ns["xsd"];
};
function DecodePrimitive(os, st, o)
{
	var r = o.hasChildNodes() ? o.firstChild.nodeValue : o.nodeValue;
	if (r == null && st == 'string')
	{
		if (st == 'string')
			return '';
		return null;
	}
	switch(_st[st])
	{
		case 0:
			r = eval(r);
			break;
		case 1 :
			break;
		case 2 :
			r = unescape(r); 
			break;
		case 3 :
		case 4:
			var aXmlDT = r.split("T");
			r = new Date();
			if (aXmlDT.length > 0)
			{
				DecDate(r, aXmlDT[0]);
				if (aXmlDT.length > 1)
					DecTime(r, aXmlDT[1]);
			}
			break;
		case 5:
			var s = r;
			r = new Date();
			DecTime(r, s);
			break;
		case 6 :
			//r = decb64(r); break;
			//alert( 'try to decb64' );
		default:
			break;
	}
	return r;
};
function DecodeArray(c, a, s, d, o, fnDec)
{
	for (var i = 0; i < s[d-1]; i++)
	{
		if (d == s.length)
			a[i] = fnDec(o[c++]);
		else
		{
			a[i] = new Array();
			c = DecodeArray(c, a[i], s, d+1, o, fnDec);
		}
	}
	return c;
};
function GetArrayInfo(o)
{
	for (var i = 0; i < o.attributes.length; i++)
	{
		var oAtt = o.attributes.item(i);
		var an = oAtt.name;
		var a = oAtt.name.split(":");
		if (a.length > 1)
			an = a[1];
		if (an != "arrayType")
			continue;
		var at = new Array();
		var asa= oAtt.value.split("[");
		if (asa.length > 1)
			ParseArrayType(at, asa[1]);
		else
			at[0] = o.childNodes.length;
		return at;
	}
	return null;
};
function EncodeVar(os, fDocEnc, v, t)
{
	var qn = t.ns == null ? "" : (t.ns + ":");
	var szBeg = fDocEnc ? ("<"+qn+t.type+' xsi:type="'+qn+t.type+'"'+">") : "";
	var szEnd = fDocEnc ? ("</" + qn + t.type + ">") : "";
	var sz = '';
	if (v == null)
		return szBeg + sz + szEnd;
	var oschm = GetSchema(os, t);
	if (isSimpleType(os, oschm, t))
	{
		if (t.fArray)
		{
			if (typeof v != 'object' && typeof v != 'unknown')
				return szBeg + sz + szEnd;
			var sArr = t.sizeArray;
			var k = 1;
			k = (sArr == null) ? 1 : sArr.length;
			//**************CONVERT VB Array to JS array NOT NEEDED RIGHT NOW
			//if (typeof v == 'unknown')
				//v = vbArrayToJs(v, k);
			sz += EncodeArray(os, t.type, v, k, EncodePrimitive);
			return szBeg + sz + szEnd;
		}
		else
		{
			sz = EncodePrimitive(os, t.type, v);
			return sz;
		}
	}
	var et = oschm.types[t.type];
	if (et == null)
	{
		try
		{
			var os = v.childNodes;
			if( os == undefined )
			{
				sz = v;
			}
			else
			{
				for (var i = 0; i < os.length; i ++)
				{
					sz += os[i].xml;
				}
			}
			return szBeg + sz + szEnd;
		}
		catch (e)
		{
			return szBeg + sz + szEnd;
		}
	}
	if (t.fArray)
	{
		if (typeof v != 'object' && typeof v != 'unknown')
			return szBeg + sz + szEnd;
		var nt = new Object();
		nt.name = t.name;
		nt.fArray = false;
		nt.type = t.type;
		nt.ns   = t.ns;
		var fnEnc = function(oS, t, vi){return EncodeVar(oS, fDocEnc, vi, nt);};
		var sArr = t.sizeArray;
		var k = 1;
		k = (sArr == null) ? 1 : sArr.length;
		//if (typeof v == 'unknown')
			//v = vbArrayToJs(v, k);
		sz += EncodeArray(os, t.type, v, k, fnEnc);
		return szBeg + sz + szEnd;
	}
	if (typeof v != 'object' || v.length > 0)
	{
		var et1 = Get1stAryItem(et);
		if (et1 == null)
			return szBeg + sz + szEnd;
		if (v.length == null || v.length == 0)
			sz += '\n<' + et1.name + '>';
		sz += EncodeVar(os, fDocEnc, v, et1);
		if (v.length == null || v.length == 0)
			sz += '</' + et1.name + '>';
		return szBeg + sz + szEnd;
	}
	for (var k in v)
	{
		if (et[k] == null)
		continue;
		if (v[k] == null)
		{
			sz += '\n<' + et[k].name + ' xsi:null="true"' + '/>\n';
			continue;
		}
		var qt = "";
		if (isPrimitive(os, et[k]))
			qt = ' xsi:type="xsd:' + et[k].type + '"';
		sz += '\n<' + et[k].name + qt + '>'
		+ EncodeVar(os, fDocEnc, v[k], et[k])
		+ '</' + et[k].name + '>';
	}
	return szBeg + sz + szEnd;
};
function EncodePrimitive(os, argType, argVal)
{
	var sz = '';
	switch(_st[argType])
	{
		case 2 :
			if (os.fEscString)
				sz = escape(argVal);
			else
				sz = "<![CDATA[" + argVal + "]]>";
			break;
		case 3 :
			try
			{
				sz  =   argVal.getFullYear()
				+   "-" + FixupDT(argVal.getMonth() + 1)
				+   "-" + FixupDT(argVal.getDate())
				+   "T" + FixupDT(argVal.getHours())
				+   ":" + FixupDT(argVal.getMinutes())
				+   ":" + FixupDT(argVal.getSeconds())
				+   (argVal.getMilliseconds==null
				? '' : ('.' + argVal.getMilliseconds()))
				+   EncTZ(argVal);
			}
			catch (e) 
			{ 
				sz = argVal; 
			}
			break;
		case 4 :
			try
			{
				sz  =   argVal.getFullYear()
				+   "-" + FixupDT(argVal.getMonth() + 1)
				+   "-" + FixupDT(argVal.getDate())
				+   EncTZ(argVal);
			}
			catch (e) 
			{ sz = argVal; }
			break;
		case 5 :
			try
			{
				sz  =   FixupDT(argVal.getHours())
				+   ":" + FixupDT(argVal.getMinutes())
				+   ":" + FixupDT(argVal.getSeconds())
				+   (argVal.getMilliseconds==null
				? '' : ('.' + argVal.getMilliseconds()))
				+   EncTZ(argVal);
			}
			catch (e) 
			{ sz = argVal; }
			break;
		case 6 :
			sz = encb64(argVal);
			break;
		default :
			sz = argVal;
	}
	return sz;
};
