//
//
//  JavaScript Refactoring for safer, faster, better AJAX.
//
//  Copyright 2005, Pavel Simakov, 
//  http://www.softwaresecretweapons.com
//
//

function oyXMLRPCProvider () { }

// checks to see if we have too many messages in log
oyXMLRPCProvider.prototype.internalCanMsg = function(){
	this.msgCount++;
	return this.msgCount < 100;
}
	
// adds message to internal log
oyXMLRPCProvider.prototype.internalOnLog = function(msg){
	if(this.onLog && this.internalCanMsg()) {
		this.onLog(msg);
	}
}
	


// adds message to internal error handler
oyXMLRPCProvider.prototype.internalOnError = function(msg){
	if(this.onError && this.internalCanMsg()) {
		this.onError(msg);
	}
}	
	
// tells us whether we are busy waiting for the response to another request
oyXMLRPCProvider.prototype.internalIsBusy = function(){
	return this.inProgress && !this.isComplete;
}	
	
// internal callback function for the browser; it is called when a state of a request object changes
oyXMLRPCProvider.prototype.internalRequestComplete = function() {
				
	var STATE_COMPLETED = 4;
	var STATUS_200 = 200;			

	if (!this.internalIsBusy()) {
		this.internalOnError("internalRequestComplete: error - no request submitted");
	}
	
	this.internalOnLog("internalRequestComplete: readyState " + this.req.readyState);

	if (this.req.readyState == STATE_COMPLETED) {
		this.status = this.req.status;
		this.inProgress = false;
		this.isComplete = true;

		this.internalOnLog("internalRequestComplete: status " + status);
		
		if (this.status == STATUS_200) {
			this.internalOnLog("internalRequestComplete: calling callback on content with length " + this.req.responseText.length + " chars");			
			if(this.onComplete) {
				this.onComplete(this.req.responseText, this.req.responseXML);
			}				 
			this.internalOnLog("internalRequestComplete: complete on " + new Date());
		} else {
			this.internalOnError("internalRequestComplete: error - bad status while fetching " + this.url);
		}
	} else {		
		// we need to review other state codes for XMLRPC provider
	}
}	
	
// call this function to figure out version of this class
oyXMLRPCProvider.prototype.getVersion = function(){
	return "1.0.0";
}
	
// call this function to figure out if current browser supports XML HTTP Requests
oyXMLRPCProvider.prototype.isSupported = function(){
	var nonEI = window.XMLHttpRequest;
	var onIE = window.ActiveXObject;
		
	if (onIE) {	    		
		onIE = new ActiveXObject("Microsoft.XMLHTTP") != null;
	}
		
	return window.XMLHttpRequest || onIE;
}
	
// call this function to find out if more calls are possible and if request has been completely received 
oyXMLRPCProvider.prototype.isBusy = function(){
	return this.internalIsBusy();
}		

//  call this function to submit new request
oyXMLRPCProvider.prototype.submit = function(_url){	
	if (this.internalIsBusy()) {
		this.internalOnError("submit: error - busy processing another request " + _url);			
	}	
		
	this.msgCount = 0;
	this.internalOnLog("submit: started on " + new Date() + " for " + _url);
				
	this.url = _url;	
	this.status = null;
	this.inProgress = true;
	this.isComplete = false;
		
        var _this = this;

	if (window.XMLHttpRequest) {
	    
	    	// branch for native XMLHttpRequest object
		this.internalOnLog("submit: using XMLHttpRequest()");
	    
	        this.req = new XMLHttpRequest();
		this.req.onreadystatechange = function() { _this.internalRequestComplete(); };
	        this.req.open("GET", this.url, true);	                

        	this.req.send(null);	 
	        	    
	 } else { 
	    	    	
		// branch for IE/Windows ActiveX version
		if (window.ActiveXObject) {	    		
		        this.req = new ActiveXObject("Microsoft.XMLHTTP");
	        	if (this.req) {
		        
				this.internalOnLog("submit: using Microsoft.XMLHTTP");
		       
				this.req.onreadystatechange = function() { _this.internalRequestComplete(); };
		            	this.req.open("GET", this.url, true);
				this.req.setrequestheader("Pragma","no-cache");
		   	    	this.req.setrequestheader("Cache-control","no-cache");
		           
		        	this.req.send();	
	        	} else {
				this.internalOnError("submit: error - unable to create Microsoft.XMLHTTP");
		        }
		} else {
			this.internalOnError("submit: error - browser does not support XML HTTP Request");
		}
	}
	
	this.internalOnLog("submit: complete");
}
	
// call this function to abort current request
oyXMLRPCProvider.prototype.abort = function(){
	this.internalOnLog("abort: " + this.url);
		
	if (!this.internalIsBusy()) {
		this.internalOnError("abort: error - no request submitted");			
	}
	
	this.onComplete = null;		
	this.req.abort();
}	

// call this function to find out current url
oyXMLRPCProvider.prototype.getUrl = function(){
		return this.url;
}
	
// call this function to find out HTTP status code after response completes
oyXMLRPCProvider.prototype.getStatus = function(){
		return this.status;
}	
	
// please can override this; this is function called when fatal error occurs
oyXMLRPCProvider.prototype.onError = function(msg){
		
} 
	
// user can override this; this function  is called when log message is created	
oyXMLRPCProvider.prototype.onLog = function(msg) {
	
}	
	
// user can override this;  this function is called when response is received without errors
oyXMLRPCProvider.prototype.onComplete = function(responseText, responseXML){
		
}
	