//*****************************************************************************
// 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_Debugger(){
	var bDebugWS = false;

	var sDebugString = '<div style="font-family: arial;text-align: center;font-size: 13px;font-weight: bold;">Client-side Web Service Debug</div><div style="text-align: center;">Total Transactions: <span id="_debugWSTotal"></span></div>'
	var sWSDefaultFontSize = '10px'
	var iDebugTransaction = 0
	var aReadyStateEnumeration = new Array('UNINITIALIZED','LOADING','LOADED','INTERACTIVE','COMPLETED')
	var aReadyStateEnumerationDescription = new Array()
	aReadyStateEnumerationDescription[0]='The object has been created, but not initialized (open has not been called).'
	aReadyStateEnumerationDescription[1]='The object has been created, but the send method has not been called.'
	aReadyStateEnumerationDescription[2]='The send method has been called and the status and headers are available, but the response is not yet available.'
	aReadyStateEnumerationDescription[3]='Some data has been received. You can call the responseBody and responseText properties to get the current partial results.'
	aReadyStateEnumerationDescription[4]='All the data has been received, and the complete data is available in the responseBody and responseText properties.'
	var dDebugTotalTimer = false
	// debug properties
	this.bDebug = bDebugWS  // boolean
	this.dStartTime  // date
	this.dEndTime  // date
	this.dTransactionDuration  // date
	this.TotalDuration  // string
	this.iTransactionNumber = 0 // int
	
	// debug methods
	this.SetStartTime = _DebugSetStartTime
	this.SetTimeStamp = _DebugSetTimeStamp
	this.SetEndTime = _DebugSetEndTime
	
	// Events
	this.ondebugcall = _DebugRequest
	this.ondebugreadystate = _DebugReadyState
	this.ondebugload = _DebugResponse
	this.ondebugerror = function (oError){
		_DebugPostError(oError)
	}
		
	this.debugHTTPError = _DebugHTTPError
	this.debugSoapFault = _DebugSoapFault
	
	
	function _DebugRequest(){
		if (this.bDebug){
			var oPostXML = this.SOAPXML
			var sOperation = this.operation
			var sTargetNamespaceURI = this.targetNamespaceURI
			var sServiceLocationURL = this.serviceLocationURL
			var sSOAPAction = this.SOAPAction
			var sProxyURL = this.proxyURL
			
			this.SetStartTime()
			iDebugTransaction++
			this.iTransactionNumber = iDebugTransaction
			
			if (!document.getElementById('_debugWSBlock')){
				var oDivContainer = document.createElement('div')
				oDivContainer.style.overflow = 'auto'
				oDivContainer.style.width = '580px'
				oDivContainer.style.height = '500px'
				oDivContainer.style.padding = '5px;'
				oDivContainer.style.margin = '5px;'
				oDivContainer.style.border = 'solid 2px #666666'
				oDivContainer.style.backgroundColor = 'white'
				oDivContainer.style.fontFamily = 'arial'
				oDivContainer.style.fontSize = sWSDefaultFontSize
				oDivContainer.style.color = '#000066'
				oDivContainer.id = '_debugWSBlock'
				document.body.appendChild(oDivContainer)
			}
			sDebugString += '<div id="_debugWSBlock_Transaction' + this.iTransactionNumber + '">'
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;border-top: solid 1px #cccccc;"><i>* Starting Transaction  ' + this.iTransactionNumber + ' *</i></div>'
			sDebugString += '<div style="font-style: italic;font-weight: bold;font-size:16px;border-bottom: dashed 1px #cccccc;">' + sOperation + '</div>'
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Target Namespace:</b> ' + sTargetNamespaceURI + '</div>'
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Service Location URL:</b> ' + sServiceLocationURL  + '</div>'
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>SOAPAction:</b> ' + sSOAPAction + '</div>'
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Proxy URL:</b> ' + sProxyURL + '</div>'
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Asynchronous:</b> ' + this.async + '</div>'
			
			sDebugString += '<div><textarea style="font-family: arial;font-size: '+sWSDefaultFontSize+';margin-left: 10px;background-color: #eeeeee;width: 540px; height: 80px;border: solid 1px #666666;">' + DOMSerialXML(this.SOAPXML) + '</textarea></div>'
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;"><i>* Posting Request *</i></div>'
			sDebugString += '</div>'
			
			document.getElementById('_debugWSBlock').innerHTML += sDebugString
			sDebugString = ''
			document.getElementById('_debugWSTotal').innerHTML = iDebugTransaction
		}
	}		
	
	function _DebugReadyState(){
		sDebugString = '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>ReadyState:</b> '
		sDebugString += '<acronym title="'+aReadyStateEnumerationDescription[this.XMLHttpRequest.readyState]+'">'
		sDebugString += aReadyStateEnumeration[this.XMLHttpRequest.readyState] + ' (' + this.XMLHttpRequest.readyState+')</acronym> '	
		sDebugString += ' - <i>Time: ' + this.SetTimeStamp() + '</i>'
		sDebugString += '</div>'
		
		document.getElementById('_debugWSBlock_Transaction' + this.iTransactionNumber).innerHTML += sDebugString
		sDebugString = ''
	}
	
	function _DebugResponse(){
		if (this.bDebug){
			this.SetEndTime()
			
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;"><i>* Receiving Response *</i></div>'
			
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>HTTP Status:</b> ' + this.debugHTTPError() + '</div>'
			
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>SOAP Status:</b> ' + this.debugSoapFault() + '</div>'
			
			sDebugString += '<div><textarea style="font-family: arial;font-size: '+sWSDefaultFontSize+';margin-left: 10px;background-color: #eeeeee;width: 540px; height: 150px;border: solid 1px #666666;">' + this.XMLHttpRequest.getAllResponseHeaders() + '\n' + XMLHTTPSerialXML(this.XMLHttpRequest) + '</textarea></div>'
			
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;margin-bottom: 20px;border-bottom: solid 1px #cccccc;"><i>* End Transaction  ' + this.iTransactionNumber + ' - Time: ' + this.TotalDuration + ' *</i></div>'
				
			document.getElementById('_debugWSBlock_Transaction' + this.iTransactionNumber).innerHTML += sDebugString
			sDebugString = ''
		}
	}
	
	function _DebugHTTPError(){
	
		var sHTTPError = ''
		var sStatus = '<div style="margin-left: 20px;font-size: '+sWSDefaultFontSize+';"><b>HTTP Code:</b> ' + this.XMLHttpRequest.status + '</div>'
		sStatus += '<div style="margin-left: 20px;font-size: '+sWSDefaultFontSize+';"><b>HTTP Text:</b> ' + this.XMLHttpRequest.statusText + '</div>'
		if (this.XMLHttpRequest.status!=200){
			sHTTPError += '<span style="color: red;font-weight: bold;font-size: '+sWSDefaultFontSize+';">HTTP Error</span>'
			sHTTPError += sStatus
			sHTTPError += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';background-color: #eeeeee;overflow: auto;width: 540px; height: 150px;border: solid 1px #666666;">' + this.XMLHttpRequest.responseText + '</div>'
		}
		else {
			sHTTPError += 'OK'
			sHTTPError += sStatus
		}
		
		return sHTTPError
	}
	
	function _DebugSoapFault(){
		try {
			var oSOAPXML = this.XMLHttpRequest.responseXML
			var colFault
			var colEnvelope
			cleanWhitespace(oSOAPXML)
			
			if (oSOAPXML.getElementsByTagNameNS){
				colEnvelope = oSOAPXML.getElementsByTagNameNS('http://schemas.xmlsoap.org/soap/envelope/','Envelope')
				colFault = oSOAPXML.getElementsByTagNameNS('http://schemas.xmlsoap.org/soap/envelope/','Fault')
			}
			else {
				colEnvelope = oSOAPXML.getElementsByTagName('soap:Envelope')
				colFault = oSOAPXML.getElementsByTagName('soap:Fault')
			}
			
			if (colFault.length > 0 || colEnvelope.length < 1){
				var sFault = '<span style="color: red;font-weight: bold;font-size: '+sWSDefaultFontSize+';">SOAP Error</span>'
				
				if (colEnvelope.length < 1){
					sFault += ' - Improper SOAP response formatting. No SOAP Envelope.'
				}
				
				if (colFault[0] && colFault[0].childNodes[0].firstChild){
					sFault += '<div style="margin-left: 20px;font-size: '+sWSDefaultFontSize+';"><b>Fault Code:</b> ' + colFault[0].childNodes[0].firstChild.nodeValue + '</div>'
				}
				if (colFault[0] && colFault[0].childNodes[1].firstChild){
					sFault += '<div style="margin-left: 20px;font-size: '+sWSDefaultFontSize+';"><b>Fault String:</b> ' + colFault[0].childNodes[1].firstChild.nodeValue + '</div>'
				}
				
			
				return sFault 
			}
			else {
				return 'OK'
			}
			
			return colFault.length
		}
		catch (oError){
			var sFault = '<span style="color: red;font-weight: bold;font-size: '+sWSDefaultFontSize+';">Parser Error</span>'
			return sFault 
		}
	}
	
	function _DebugPostError(oError){
		if (this.bDebug){
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;"><i>* Post Failed *</i></div>'
			
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Error Status:</b> <span style="color: red;font-weight: bold;">Post Error</span></div>'
			
			sDebugString += '<div style="margin-left: 10px;font-size: '+sWSDefaultFontSize+';"><b>Error Description:</b> '
				if (e.description){
					sDebugString += oError.description
				}
				else {
					sDebugString += oError
				}
			sDebugString += '</div>'
			
			sDebugString += '<div style="font-size: '+sWSDefaultFontSize+';text-align: right;margin-bottom: 20px;border-bottom: solid 1px #cccccc;"><i>* End Transaction  ' + this.iTransactionNumber + ' - Time: ' + this.TotalDuration + ' *</i></div>'
				
			document.getElementById('_debugWSBlock_Transaction' + this.iTransactionNumber).innerHTML += sDebugString
			sDebugString = ''
		}
		else {
			if (oError.description){
				alert(oError.description)
			}
			else {
				alert(oError)
			}
		}
	}
	
	function _DebugSetStartTime(){
		this.dStartTime = new Date()
		if (!dDebugTotalTimer){
			dDebugTotalTimer = new Date(0)
		}
	}
	
	function _DebugSetTimeStamp(){
		this.dEndTime = new Date()
		var milliTimeStarted = this.dStartTime.getTime()
		var milliTimeChecked = this.dEndTime.getTime()
		this.dTransactionDuration = new Date(milliTimeChecked - milliTimeStarted)
		
		var iHours = Math.floor(this.dTransactionDuration.getTime()/(3600000))
		var iMins = this.dTransactionDuration.getUTCMinutes()
		var iSecs = this.dTransactionDuration.getUTCSeconds()
		var iMills = this.dTransactionDuration.getUTCMilliseconds()
		
		iHours = (iHours < 10)?'0'+iHours:iHours
		iMins = (iMins < 10)?'0'+iMins:iMins
		iSecs = (iSecs < 10)?'0'+iSecs:iSecs
		iMills = (iMills < 10)?'0'+iMills:iMills
		
		this.TotalDuration = iHours+':'+iMins+':'+iSecs+'.'+iMills
		return this.TotalDuration
	}
	
	function _DebugSetEndTime(){
		var sTimeStamp = this.SetTimeStamp()
		
		_DebugAddDurationToTotal(this.dTransactionDuration)

	}
	
	function _DebugAddDurationToTotal(dTransactionDuration){
	
		var milliTotalTransactions = dDebugTotalTimer.getTime()
		var milliTransDuration = dTransactionDuration.getTime()
	
		dDebugTotalTimer = new Date(milliTotalTransactions + milliTransDuration)
		var iHours = Math.floor(dDebugTotalTimer.getTime()/(3600000))
		var iMins = dDebugTotalTimer.getUTCMinutes()
		var iSecs = dDebugTotalTimer.getUTCSeconds()
		var iMills = dDebugTotalTimer.getUTCMilliseconds()
		
		iHours = (iHours < 10)?'0'+iHours:iHours
		iMins = (iMins < 10)?'0'+iMins:iMins
		iSecs = (iSecs < 10)?'0'+iSecs:iSecs
		iMills = (iMills < 10)?'0'+iMills:iMills
		
		var sDuration = iHours+':'+iMins+':'+iSecs+'.'+iMills
	
		document.getElementById('_debugWSTotal').innerHTML = iDebugTransaction + ' - Total Time: ' + sDuration + ' <span style="font-style: italic;font-size: 9px;">(hh:mm:ss.mm)</span>'
	}
	
	function XMLHTTPSerialXML(StatusxmlHTTP) {
		try {
			if (window.XMLSerializer){
				var s = new XMLSerializer()
				var d = StatusxmlHTTP.responseXML;
				str = s.serializeToString(d);
				return str
			}
			else {
				return StatusxmlHTTP.responseXML.xml
			}
		}
		catch (oError){
			return 'parser error'
		}
	}
	
	function DOMSerialXML(StatusDOM) {
		if (window.XMLSerializer){
			var s = new XMLSerializer()
			str = s.serializeToString(StatusDOM);
			return str
		}
		else {
			return StatusDOM.xml
		}
	}
	
	var notWhitespace = /\S/
	
	function cleanWhitespace(node) {
	  for (var x = 0; x < node.childNodes.length; x++) {
	    var childNode = node.childNodes[x]
	    if ((childNode.nodeType == 3)&&(!notWhitespace.test(childNode.nodeValue))) {
	// that is, if it's a whitespace text node
	      node.removeChild(node.childNodes[x])
	      x--
	    }
	    if (childNode.nodeType == 1) {
	// elements can have text child nodes of their own
	      cleanWhitespace(childNode)
	    }
	  }
	}
	
	function queryStringValue(sVariable){
		var sQuery = location.search
		var sLookup = sVariable.toLowerCase() + '='
		
		if (sQuery.toLowerCase().indexOf(sLookup)!=-1){
			var iStartLookup = sQuery.toLowerCase().indexOf(sLookup) + sLookup.length
		}
		else {
			return false
		}
		
		var sCheck = sQuery.substring(iStartLookup,sQuery.length)

		if (sCheck.indexOf('&amp;')!=-1){
			var iEnd = sCheck.indexOf('&amp;')
		}
		else {
			var iEnd = sCheck.length
		}
		
		var sValue = sCheck.substring(0,iEnd)
		
		return unescape(sValue)
	}
	
	// check for debug in querystring
	var sQueryStringDebug = queryStringValue('bDebugWS')
	if (sQueryStringDebug){
		this.bDebug = true;
	}
	
}

// The WebService Class inheriates the Debugger class
WebService.prototype = new WebService_Debugger