//*****************************************************************************
// These terms of use permit anyone the right to use and modify this software  
// without limitations as long as proper credits are given by not removing this 
// notice and any custom modifications are noted in the code. 
// Please submit any suggestions for updates to http://www.kuhnhaus.com
// Copyright 2004 by Mark Kuhn.
//*****************************************************************************

function WebService(operation,targetNamespaceURI,serviceLocationURL,SOAPAction,proxyURL){
		
	// properties
	this.operation = operation; // public
	this.targetNamespaceURI = targetNamespaceURI; // public
	this.serviceLocationURL = serviceLocationURL; // public
	this.SOAPAction = SOAPAction; // public
	this.proxyURL = proxyURL; // public
	this.async = true; // public
	// collections - indexed and named
	this.params = new Array(); // public
	
	// methods
	this.call = _Call; // public
	this.stop = _Stop; // public
	this.addParam = function (name,value,datatype){ // public
		this.params[this.params.length] = this.params[name] = new _SoapParam(name,value,datatype)
	}
	this.createSOAPXML = _CreateSOAPXML; // private
	this.checkRequiredProperties = _CheckRequiredProperties; // private
	this.assembleProxyURL = _AssembleProxyURL; // private
	this.firePreEvents = _FirePreEvents; // private
	this.executePost = _ExecutePost; // private
	this.bStopped = false; // private
	
	// child objects
	this.XMLDOM = _XMLDOM // private
	this.XMLHttpRequest; // private
	this.SOAPXML; // private
	
	var oWS_SelfRef = this
	this.firePostEvents = function (){
		
		// Insert ondebugreadystate Event
		try {
			if (typeof oWS_SelfRef.ondebugreadystate == "function" && !oWS_SelfRef.bStopped){
	        	if (oWS_SelfRef.bDebug)
	        	oWS_SelfRef.ondebugreadystate();
			}
		}
		catch (oError){
			//alert('WebService Error: \nError in the ondebugreadystate event: \n' + oError)
		}
		
		if (typeof oWS_SelfRef.onstatechange == "function" && !oWS_SelfRef.bStopped){
			oWS_SelfRef.onstatechange();
		}
		
		// Fire Post Events when the readystate is 4
		if (oWS_SelfRef.XMLHttpRequest.readyState == 4 && !oWS_SelfRef.bStopped) {
			_FirePostEvents(oWS_SelfRef)
		}
	}
	
	// events
	this.oncall // public
	this.onstatechange // public
	this.onload // public
	this.onerror // public
	this.onstop // public
	
	this.ondebugcall // private
	this.ondebugreadystate // private
	this.ondebugload // private
	this.ondebugerror // private
		
	function _SoapParam(name,value,datatype){
		this.name = name
		this.value = value
		this.datatype = datatype
	}
		
	function _XMLHttpRequest(){
		try {	
			if (window.XMLHttpRequest){
				var XMLHttp = new XMLHttpRequest();
				// some older versions of Moz did not support the readyState property and the onreadystate event
				 if (XMLHttp.readyState == null) {
			        XMLHttp.readyState = 1;
			        XMLHttp.addEventListener("load", function () {
			           XMLHttp.readyState = 4;
			           if (typeof XMLHttp.onreadystatechange == "function")
			              XMLHttp.onreadystatechange();
			        }, false);
			     }
			
				return XMLHttp
		    }
		    else if (window.ActiveXObject){
				var XMLHttp
		 
				try {
					XMLHttp = new ActiveXObject("Msxml2.XMLHTTP")
				}
				catch (e) {
					try {
						XMLHttp = new ActiveXObject("Microsoft.XMLHTTP")
					}
					catch (e) {
						XMLHttp = false
					}
				}
				return XMLHttp
		    }
		}
		catch (oError) {}
		//alert('WebService Error: \nThe browser does not support the XMLHttpRequest object.');
	}
	
	function _XMLDOM(){
		try {
			if (document.implementation && document.implementation.createDocument){
				return document.implementation.createDocument("", "", null);
			}
			else if (window.ActiveXObject){
				return new ActiveXObject("Msxml2.DOMDocument")
				//return new ActiveXObject("Microsoft.XmlDom");
		    }
		}
		catch (oError) {}
		//alert('WebService Error: \nThe browser does not support the XML DOM object.');
	}
	
	function _Call(){
		this.XMLHttpRequest = new _XMLHttpRequest();
		
		if (this.async && !this.bStopped){
			this.XMLHttpRequest.onreadystatechange = this.firePostEvents;	
		}
		
		if (this.firePreEvents() && !this.bStopped){
			if (this.checkRequiredProperties()){
				this.createSOAPXML();
				this.assembleProxyURL();			
				this.executePost();
			}
		}
		
		if (!this.async && !this.bStopped){
			this.firePostEvents();	
		}
	}

	function _Stop(){
		this.XMLHttpRequest.abort();
		this.bStopped = true;
		if (typeof this.onstop == "function"){
			this.onstop();
		}
	}
	
	function _CheckRequiredProperties(){
		if (this.operation == null || this.operation.length == 0){
			//alert('WebService Error: \nThe operation property needs to be defined.');
			return false
		}
		if (this.targetNamespaceURI == null || this.targetNamespaceURI.length == 0){
			//alert('WebService Error: \nThe targetNamespaceURI property needs to be defined.');
			return false
		}
		if (this.serviceLocationURL == null || this.serviceLocationURL.length == 0){
			//alert('WebService Error: \nThe serviceLocationURL property needs to be defined.');
			return false
		}
		if (this.SOAPAction == null || this.SOAPAction.length == 0){
			//alert('WebService Error: \nThe SOAPAction property needs to be defined.');
			return false
		}
		return true
	}
	
	function _AssembleProxyURL(){
	 	if (this.proxyURL!=null && this.serviceLocationURL.indexOf(this.proxyURL)==-1){
			this.serviceLocationURL = this.proxyURL + '?URL=' + this.serviceLocationURL + '&SOAPAction=' + this.SOAPAction
	    }
	}
	
	function _FirePreEvents(){
		
		// Insert oncall Event
		try {
			if (typeof this.oncall == "function" && !this.bStopped){
				if (this.oncall()){
					return true
				}
				else {
					return false
				}
			}
		}
		catch (oError){
			//alert('WebService Error: \nError in the oncall event: \n' + oError)
		}
		return true
	}
	
	function _ExecutePost(){
		// Insert ondebugcall Event
		try {
			if (typeof this.ondebugcall == "function" && !this.bStopped){
				if (this.bDebug)
				this.ondebugcall();
			}
		}
		catch (oError){
			//alert('WebService Error: \nError in the ondebugcall event: \n' + oError)
		}
		try {
			this.XMLHttpRequest.open("POST", this.serviceLocationURL, this.async);
			this.XMLHttpRequest.setRequestHeader("SOAPAction", this.SOAPAction);
	    	this.XMLHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");

			this.XMLHttpRequest.send(this.SOAPXML);
		}
		catch (oError) {
			if (typeof this.ondebugerror == "function" || typeof this.onerror == "function"){
				
				// Insert ondebugerror Event
				if (typeof this.ondebugerror == "function"){
		        	if (this.bDebug)
		        	this.ondebugerror(oError);
				}
				
				// Insert onerror Event
				if (typeof this.onerror == "function"){
		        	this.onerror(oError);
				}
			}
			else {
				//alert('WebService Error: \nError occured during the post: \n' + oError)
			}	
	    } 
	}
	
	function _FirePostEvents(oWebService){
			var oEvent = {
				returnValue: true 
			}
			// Insert ondebugload Event
			try {
				if (typeof oWebService.ondebugload == "function" && !oWebService.bStopped){
		        	if (oWebService.bDebug)
		        	oWebService.ondebugload();
				}
			}
			catch (oError){
				//alert('WebService Error: \nError in the ondebugload event: \n' + oError)
			}
			
			// Insert onload Event
			try {
				if (typeof oWebService.onload == "function" && !oWebService.bStopped){
		        	oWebService.onload(oEvent);
				}
			}
			catch (oError){
				//alert('WebService Error: \nError in the onload event: \n' + oError)
			}
			
			// clear params
			oWebService.params.length = 0
	}
	
	function _CreateSOAPXML(){
		this.SOAPXML = null;
		this.SOAPXML = new this.XMLDOM();
		
	    var oEnv = this.SOAPXML.createElement('soap:Envelope')
			var	oNamespace = this.SOAPXML.createAttribute('xmlns:soap')
				oNamespace.value = 'http://schemas.xmlsoap.org/soap/envelope/'
				oEnv.attributes.setNamedItem(oNamespace)
	
			this.SOAPXML.appendChild(oEnv)	
	
	    var oNamespace = this.SOAPXML.createAttribute('xmlns:xsi')
			oNamespace.value = 'http://www.w3.org/2001/XMLSchema-instance'
			this.SOAPXML.documentElement.attributes.setNamedItem(oNamespace)
		
			oNamespace = this.SOAPXML.createAttribute('xmlns:xsd')
			oNamespace.value = 'http://www.w3.org/2001/XMLSchema'
			this.SOAPXML.documentElement.attributes.setNamedItem(oNamespace)
			
			oNamespace = this.SOAPXML.createAttribute('xmlns')
			oNamespace.value = this.targetNamespaceURI
			this.SOAPXML.documentElement.attributes.setNamedItem(oNamespace)
			
			var oBody = this.SOAPXML.createElement('soap:Body')
			this.SOAPXML.documentElement.appendChild(oBody)
			
		var oOperation = this.SOAPXML.createElement(this.operation)	
			oNamespace = this.SOAPXML.createAttribute('xmlns')
			oNamespace.value = this.targetNamespaceURI
			oOperation.attributes.setNamedItem(oNamespace)
			oBody.appendChild(oOperation)
			
			var oParam
			var oValue
			for (i=0; i < this.params.length; i++){
				oParam = this.SOAPXML.createElement(this.params[i].name)
				oValue = this.SOAPXML.createTextNode(this.params[i].value)
				
				oNamespace = this.SOAPXML.createAttribute('xmlns')
				oNamespace.value = this.targetNamespaceURI
				oParam.attributes.setNamedItem(oNamespace)
				oParam.appendChild(oValue)
				oBody.appendChild(oOperation)
				
				oOperation.appendChild(oParam)
			}
	}
}
