// JsonRequest: multi-threaded ajax/json request handler
// callback function accepts two arguments- data, and request type
// VERSION 1.1 - removed instance name dependency, replaced with 'that' variable and closures
// NOTE - leave mn argument for backwards compatibility 
function JsonRequest(mn, cb){
	//this.mn = mn;
	this.cb = typeof mn === 'function' ? mn : cb; // callback for successful 
	this.ecb = function(r){alert(r['message'] ? r['message'] : 'Error id: ' + r['error'])};
	this.threads = [];
	this.threadsBusy = [];
};
JsonRequest.prototype.setErrorCallback = function(c){
	this.ecb = c; // callback function to be called each time the list is updated
};

// rType is passed through to the callback function if set, to identify what sort of request was made
JsonRequest.prototype.makeRequest = function(url,p,rType){
	var that = this, i;
	//console.log('makeRequest  ', rType, url);


	if (!p) p = null;
	
	url += (url.indexOf('?') > -1 ? '&' : '?') + 'json=1';
	
	
	//$('messages').innerHTML += url + '<br>';	
	
	
	// get idle (or new) thread
	if (!(i = this.getThread()) == null) return false;
	r = this.threads[i];
	
	//console.log('thread: ',i);	



	// set up the request
	if (p){
		r.open('POST', url, true);
		r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		r.setRequestHeader("Content-length", p.length);
		r.setRequestHeader("Connection", "close");
	}
	else r.open('GET', url, true);
	
	// set up the callback function
	if (typeof rType === 'function')
		r.onreadystatechange = function(){ 
			if (that.threads[i].readyState == 4){
				that.clearThread(i);
				rType(that.evalR(that.threads[i].responseText));
			}
		};
	else if (this.callback)
		r.onreadystatechange = function(){ 
			if (that.threads[i].readyState == 4){
				that.clearThread(i);
				that.callback(that.evalR(that.threads[i].responseText), rType);
			}
		};
	else
		r.onreadystatechange = function(){
			if (that.threads[i].readyState == 4)
				that.clearThread(i); 
		};

	try {
		// send the request - if it fails return false
		r.send(p);
	}
	catch (e){
		return false;
	}
	
	return true;
};
// sets a current request object to available - UPDATED 5/02/08 - don't reuse threads in IE6 - DISABLED
JsonRequest.prototype.clearThread = function(i){
//	if (window.XMLHttpRequest){
		var that = this;
		setTimeout(function(){that.threadsBusy[i] = false;},2000);
//	}
};

JsonRequest.prototype.callback = function(r, t){

	if (r['error']) this.ecb(r);
	else this.cb(r,t);
};
// find an unused request object, or 
JsonRequest.prototype.getThread = function(){
	for (var i = 0; i < this.threads.length; i++){
		//if (this.threads[i].readyState == 0 || this.threads[i].readyState == 4) return i;
		if (!this.threadsBusy[i]) break;
	}
	if (!this.threads[i]){
		this.threads[i] = this.makeObj();
	}
	this.threadsBusy[i] = true;	
	return this.threads[i] ? i : null;
};
// create a new XMLHttpRequest object
JsonRequest.prototype.makeObj = function(){
	if (window.XMLHttpRequest) // Mozilla, Safari,...
		r = new XMLHttpRequest();
  else if (window.ActiveXObject) { // IE
    try {
        r = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
          r = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {}
  }}
		
	return r ? r : false;
};
JsonRequest.prototype.evalR = function(j){
	return (j != '()' && j) ? eval('(' + j + ')') : {};
};