function getXmlHttpPrefix() {
	if (getXmlHttpPrefix.prefix)
		return getXmlHttpPrefix.prefix;
	
	var prefixes = ["Msxml2", "Microsoft", "Msxml", "Msxml3"];
	var o;
	for (var i = 0; i < prefixes.length; i++) {
		try {
			// try to create the objects
			o = new ActiveXObject(prefixes[i] + ".XMLHTTP");
			return getXmlHttpPrefix.prefix = prefixes[i];
		}
		catch (ex) {};
	}
	
	throw new Error("Could not find an installed XMLHttp object");
}

function getXmlHttpRequest(){
	try {
		// NS & MOZ
		if (window.XMLHttpRequest) {
			var req = new XMLHttpRequest();
			if (req.readyState == null) {
				req.readyState = 1;
				req.addEventListener("load", function () {
					req.readyState = 4;
					if (typeof req.onreadystatechange == "function")
						req.onreadystatechange();
				}, false);
			}
			if(req.overrideMimeType){
				req.overrideMimeType('text/xml');
				return req;
			}			
		}
		// IE
		if (window.ActiveXObject) {
			var req = new ActiveXObject(getXmlHttpPrefix() + ".XMLHTTP");			
			return req;
		}
	}
	catch (ex) {}
	// Fail
	throw new Error("Your browser does not support XmlHttp objects");
}

function AJAX(gateway, async, events){
	this.gateway = gateway;
	this.transport = null;
	this.xml=false;
	if (typeof(async) == 'undefined') {
		this.async = true;
	} else {
		this.async = async;
	}

	this.events = {
			onLoading: AJAX.Default.showLoading,
			onFinish: new Function(),
			onException: AJAX.Default.showException,
			onError: AJAX.Default.showError
	};
	for (func in events) {
    	this.events[func] = events[func];
  	}
}

AJAX.prototype.remoteCall = function(service, params, callback){
	var idx = service.indexOf(".");
		
	var serviceId = service.substring(0,idx);
	var method = service.substring(idx+1,service.length);
	var c = (this.gateway.indexOf('?')>=0)?'&':'?';
	var newUrl = this.gateway+c+"bean="+encodeURIComponent(serviceId)+"&method="+method;
		
	if(params){
		for(param in params){
			newUrl += "&"+param + "=" + encodeURIComponent(params[param]);
			if(param == 'xml'){
				this.xml = params[param];
			}
		}
	}
	
	this.transport = getXmlHttpRequest();
	this.transport.open("GET", newUrl, this.async);
	this.transport.send(null);
	this.currentCallback = callback;
	if (this.async) {
		var ajax = this;
		this.transport.onreadystatechange = function(){
			if (ajax.transport.readyState == 4) {
				ajax.response();
			}
		};
		this.events["onLoading"](true);
	} else { 
		this.response();
	}
};


AJAX.prototype.response = function() {
	if (this.transport.status == '200') {
		var data = this.xml?this.transport.responseXML:this.transport.responseText;
				
		this.events["onLoading"](false);
		this.currentCallback(data);
		this.events["onFinish"](data);
	} else {
		this.events["onError"](this.transport.responseText);
	}
};

AJAX.Default = {
	loadingPane:null,
	errorPane:null,
	
	showLoading : function(state) {
		this.loadingPane = document.getElementById("buffalo_loading");
		if (this.loadingPane == null) {
			var el = document.createElement('DIV');
			el.setAttribute("id","buffalo_loading");
			el.style.cssText="display:none;font-family:Verdana;font-size:11px;border:1px solid #00CC00;background-color:#A4FFA4;padding:1px;position:absolute; right:1px; top:1px; width:110px; height:14px; z-index:10000";
			el.innerHTML="loading... ";
			document.body.appendChild(el);
			this.loadingPane = el;
		}
		if (state) {
			this.loadingPane.style.display="block";
			this.loadingPane.style.top = document.body.scrollTop+1;
		} else {
			this.loadingPane.style.display="none";
		}
	},
	
	showError: function(errorStr) {
		this.errorPane = document.getElementById("buffalo_error");
		if (this.errorPane == null) {
			var el = document.createElement('DIV');
			el.setAttribute("id","buffalo_error");
			el.style.cssText="font-family:Verdana;font-size:11px;border:1px solid #00CC00;background-color:#fff;padding:1px;position:absolute;overflow:auto; right:1px; top:1px; width:500px; height:300px; z-index:1";
			el.innerHTML=errorStr;
			document.body.appendChild(el);
			this.errorPane = el;
		}
	},
	
	showException: function(ex) { /*TODO*/ }
}
