// Based on JavaScript Refactoring for safer, faster, better AJAX.
// (Copyright 2005, Pavel Simakov)
// Original file: http://www.softwaresecretweapons.com/jspwiki/articles/JavaScriptRefactoring/new/oyXMLRPC.js
// Article: http://www.softwaresecretweapons.com/jspwiki/Wiki.jsp?page=JavascriptRefactoringForSaferFasterBetterAJAX

// Modifications:
// REWROTE creation of XMLHTTPRequest object, removing redundant calls to
// req.onreadystatechange, req.open, and req.send
// REWROTE this.onError function to open a new window and display the error,
// or place error in an alert box if popups are blocked.
if (!PbD) { var PbD = new Object(); };

PbD.HTTPReqObj = function() {	

	var status = null;
	var url = null;	
	var req = null;
	var msgCount = 0;	
	var inProgress = false;
	var isComplete = false;
	var HTTPReqObj = this;
	var _XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
	var asActiveX = false;
	var asNative = false;
	
	// checks to see if we have too many messages in log
	var internalCanMsg = function(){
		msgCount++;
		return msgCount < 100;
	}
	
	// adds message to internal log
	var internalMsgLog = function(msg){
		if(HTTPReqObj.onLog && internalCanMsg()) {
			HTTPReqObj.onLog(msg);
		}
	}
	
	// adds message to internal error handler
	var internalOnError = function(msg){
		if(HTTPReqObj.onError && internalCanMsg()) {
			HTTPReqObj.onError(msg);
		}
	}	
	
	// tells us whether we are busy waiting for the response to another request
	var internalIsBusy = function(){
		return inProgress && !isComplete;
	}	
	
	// internal callback function for the browser; it is called when a state of a request object changes
	var internalRequestComplete = function() {
				
		var STATE_COMPLETED = 4;
		var STATUS_200 = 200;
				
		if (!internalIsBusy()) {
			internalOnError("internalRequestComplete: error - no request submitted");
		}
		
		internalMsgLog("internalRequestComplete: readyState " + req.readyState);
		
		if (req.readyState == STATE_COMPLETED) {
			status = req.status;
			inProgress = false;
			isComplete = true;

			internalMsgLog("internalRequestComplete: status " + status);
			
			if (status == STATUS_200) {
				internalMsgLog("internalRequestComplete: calling callback on content with length " + req.responseText.length + " chars");			
				if(HTTPReqObj.onComplete) {
					HTTPReqObj.onComplete(req.responseText, req.responseXML);
				}				 
				internalMsgLog("internalRequestComplete: complete on " + new Date());
			} else {
				internalOnError("internalRequestComplete: error - bad status while fetching " + url);
			}
		} else {
			// we need to review other state codes for XMLRPC provider
		}
	}	
	
	// call this function to figure out version of this class
	this.getVersion = function(){
		return "1.0.0";
	}
	
	// call this function to figure out if current browser supports XML HTTP Requests
	this.isSupported = function() {
		var last_e = null;
		try{ http = new XMLHttpRequest(); } catch(e) { }
		if(!http) {
			for(var i=0; i<3; ++i) {
				var progid = _XMLHTTP_PROGIDS[i];
				try{
					http = new ActiveXObject(progid);
				} catch(e) {
					last_e = e;
				}
				if(http) {
					_XMLHTTP_PROGIDS = [progid];  // so faster next time
			 		break;
			 	}
			}
		}
		return http;
	}
	
	// call this function to find out if more calls are possible and if request has been completely received 
	this.isBusy = function(){
		return internalIsBusy();
	}		

	//  call this function to submit new request
	this.submit = function(_url) {	
		if (internalIsBusy()) {
			internalOnError("submit: error - busy processing another request " + _url);			
		}	
		
		msgCount = 0;
		internalMsgLog("submit: started on " + new Date() + " for " + _url);
				
		url = _url;	
		status = null;
		inProgress = true;
		isComplete = false;


		if (window.XMLHttpRequest){
			// If IE7, Mozilla, Safari, etc: Use native object
			req = new XMLHttpRequest()
		} else {
			if (window.ActiveXObject) {
				asActiveX = true;
				for(var i=0; i<3; ++i) {
					var progid = _XMLHTTP_PROGIDS[i];
					try {
						req = new ActiveXObject(progid);
					} catch(e) {
						last_e = e;
					}
					if(req) {
						_XMLHTTP_PROGIDS = [progid];  // so faster next time
				 		break;
				 	}
				}
			}
		}

		
		if (req) {
			if (req.overrideMimeType) {
				req.overrideMimeType('text/xml');
			}
			
			req.open("GET", url, true);
			req.onreadystatechange = internalRequestComplete;
			if(asActiveX) {
				req.setrequestheader("Pragma","no-cache");
				req.setrequestheader("Cache-control","no-cache");
			}
			req.send(null);	
		} else {
			internalOnError("submit: error - browser does not support XML HTTP Request");
		}
		internalMsgLog("submit: complete");
	}
	
	// call this function to abort current request
	this.abort = function(){
		internalMsgLog("abort: " + url);
		
		if (!internalIsBusy()) {
			internalOnError("abort: error - no request submitted");			
		}
	
		onComplete = null;		
		req.abort();
	}	

	// call this function to find out current url
	this.getUrl = function(){
		return url;
	}
	
	// call this function to find out HTTP status code after response completes
	this.getStatus = function(){
		return status;
	}	
	
	// please can override this; this is function called when fatal error occurs
	this.onError = function(msg){
		var errorWin;
		try { // Create new window and display error
			errorWin = window.open('', 'errorWin');
			var oldMsg = errorWin.document.body.innerHTML;
			errorWin.document.body.innerHTML = msg+'<br />'+oldMsg;
		}
		catch(e) { // If pop-up gets blocked, inform user
			alert(msg);
		}
	} 
	
	// user can override this; this function  is called when log message is created	
	this.onLog = function(msg) {
		/*var errorWin;
		try { // Create new window and display error
			errorWin = window.open('', 'errorWin');
			var oldMsg = errorWin.document.body.innerHTML;
			errorWin.document.body.innerHTML = msg+'<br />'+oldMsg;
		}
		catch(e) { // If pop-up gets blocked, inform user
			alert('can\'t open error window');
		}*/
	}	
	
	// user can override this;  this function is called when response is received without errors
	this.onComplete = function(responseText, responseXML) {
		internalOnError("You haven't told me what to do with the response!!");
	}
	
}