if (!window.XMLHttpRequest) {
	window.XMLHttpRequest = function() {
		return new ActiveXObject('Microsoft.XMLHTTP');
	}
}

var Ajax = function(_targetOrComplete, _url/*, _requestMethod*/){
	this.KEY = this.createInstance();

	this.before = function(){ return true; } ;
	this.onError = function () { alert("Ocorreu um erro ao executar a ação solicitada." + (DEV ? ' ('+this.xmlHttp.statusText+')' : '' ) + '.'); };
	this.onComplete = this.content;
	this.target = $("corpo");
	this.tempTarget = null;
	this.feedBack = null;
	this.requestMimeType = "text/html; charset=utf-8";
	this.method = "get";
	this.params = "";
	this.baseUrl = URL + "application/js/ajax/";
	this.historyControl = null;
	this.ifrName = "iframeHistory";
	var xmlHttp = null;
	xmlHttp = new XMLHttpRequest();
	if(!xmlHttp) alert("Esta página utiliza um controle ActiveX.\nPor favor, habilite os controles ActiveX em seu browser e tente novamente.");
	else this.xmlHttp = xmlHttp;

	if(_targetOrComplete!=null) {
		if(typeof _targetOrComplete == 'function') this.setComplete(_targetOrComplete);
		else this.setTarget(_targetOrComplete);
	}
	if(arguments[2]!=null) this.setRequestMethod(arguments[2]);
	if(_url!=null) this.callServer(_url);
}
/* sets */
Ajax.prototype.setRequestMethod = function(requestMethod) {
	if(requestMethod=='xml') requestMethod = true;
	this.requestMethod = requestMethod;
	if(requestMethod){
		if (this.xmlHttp.overrideMimeType) this.xmlHttp.overrideMimeType('text/xml; charset=utf-8');
		this.setRequestMimeType('text/xml; charset=utf-8');
	}
};
Ajax.prototype.setRequestMimeType = function(mimeType) { this.requestMimeType = mimeType; };
Ajax.prototype.setMethod = function(method){ this.method = method.toLowerCase(); };
Ajax.prototype.setFeedBack = function(element){ this.feedBack = $(element); };

Ajax.prototype.setTarget = function(target) {
	target = (typeof target=='string') ? $(target) : target ;
	this.target = target;
};

Ajax.prototype.setTempTarget = function(target) {
	target = (typeof target=='string') ? $(target) : target ;
	this.tempTarget = target;
};

Ajax.prototype.setBefore = function(before){ this.before = before; };
Ajax.prototype.setError = function(error){
	if((typeof error) == "function") this.onError = error;
	else {
		this.onError = function(){ alert(error); };
	}
};
Ajax.prototype.setComplete = function(complete){
	if((typeof complete) == "function")	this.onComplete = complete;
	else this.onComplete = function(){ alert(complete); };
};

/* feedBack */
Ajax.prototype.activateHistoryControl = function(){ this.historyControl = true; }
Ajax.prototype.destroyHistoryControl = function(){ this.historyControl = false; }

Ajax.prototype.makeFeedBack = function(label, id)
{
	var id = isset(id) ? id : "activity";
	var label = isset(label) ? label : "Processando";

	if(!$(id))
	{
		var d = DOM.create("div");
		d.setAttribute("id", id);
		d.innerHTML = this.fixIeWindow(id);

		var l = DOM.create('span');
		l.innerHTML = label;
		DOM.inside(l, d);

		DOM.inside(d , document.body);
	}
	this.feedBack = d;
};

Ajax.prototype.fixIeWindow = function(id){
	var idFrame = id + 'iframe';
	if(isMSIE) return '<iframe id="' + idFrame + '" src="javascript:false;" scrolling="no" frameborder="0" style="filter:Alpha(opacity=0);position:absolute;top:0px;left:0px;display:block;width:300px;height:300px;margin:-2px;z-index:-100" width="100%" height="100%"></iframe>';
	return "";
}

Ajax.prototype.changeFeedBackText = function( state )
{
	if(!this.feedBack) return;

	var l = '';
	switch(state)
	{
		case 0: l='Requisitando'; break;
		case 1: l='Enviando'; break;
		case 2: l='Enviado'; break;
		default: l='Carregando'; break;
	}
	var f = $t('span', this.feedBack);

	if(f)
		f[0].innerHTML = l;
	else
		this.feedBack.innerHTML = l;
}

/* methods */
Ajax.prototype.hideFeedBack = function(){
	if(!this.feedBack) return;
	this.feedBack.style.visibility = "hidden";
	this.feedBack.style.display = "none";
}
Ajax.prototype.showFeedBack = function(){
	if(!this.feedBack) return;
	this.feedBack.style.visibility = "visible";
	this.feedBack.style.display = "block";
}

Ajax.prototype.noCache = function()
{
	this.xmlHttp.setRequestHeader("Cache-Control", "no-store, no-cache, must-revalidate");
	this.xmlHttp.setRequestHeader("Cache-Control", "post-check=0, pre-check=0");
	this.xmlHttp.setRequestHeader("Pragma", "no-cache");
}
Ajax.prototype.reviewParams = function(/*params*/)
{
	if(!arguments[0]) return false;
	var params = arguments[0];
	if(params.toString().length==0) return false;

	if(this.method=="post") {
		this.params = params.substring(1);
		return;
	}

	this.params = encodeURIComponent(params);
	this.params = this.params.replace(/%3F/gi,"&"); // &
	this.params = this.params.replace(/%26/gi,"&"); // ?
	this.params = this.params.replace(/%3D/gi,"="); // =

	this.params = "?" + this.params.substring(1);
	return this.params;
}

/* calling the server */
Ajax.prototype.callServer = function(url/*, params*/)
{

	if(!this.before()){
		this.method='get';
		this.before=function() { return true; }
		return false;
	}

	if ( arguments[1] ) {
		// if any argument is passed, then the arguments on the url
		// is cleaned
		url = url.split('?')[0];
		this.reviewParams(arguments[1]);
	}
	else if( url.indexOf('?')!=-1 )
	{
		var pUrl = url.split('?');
		this.reviewParams(pUrl[1]);
		url = pUrl[0];
	} else this.params = '';

	this.url = url;

	if(this.historyControl!=null && this.historyControl!=false && this.method!='post'){
		this.historyControl = false;
		this.callIframe();
		window.backButton = this;
		return;
	}

	this.url = (this.method=="post")? url : url + this.params;

	if( this.method!='post' )
		this.xmlHttp.abort();

	this.open();

};

Ajax.prototype.open = function() {
	this.showFeedBack();
	this.xmlHttp.open(this.method, this.url, true);

	var g = this;
	this.xmlHttp.onreadystatechange = function(){
		g.changeFeedBackText(g.xmlHttp.readyState);
		if (g.xmlHttp.readyState == 4) {
			if (g.xmlHttp.status==200) {
				var r = (g.requestMethod)? g.xmlHttp.responseXML : g.fixCall(g.xmlHttp.responseText);
				g.onComplete(r);
				g.hideFeedBack();
				if(g.historyControl == false) g.activateHistoryControl();
				return true;
			}else if( g.xmlHttp.status == 0 ){
				g.hideFeedBack();
				return false;
			} else {
				g.onError();
				g.hideFeedBack();
				if(g.historyControl == false) g.activateHistoryControl();
				return false;
			}
		}
	}

	if(this.method=="post") {
		this.xmlHttp.setRequestHeader("X-Requested-With", "XmlHttpRequest");
		this.xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
		this.noCache();
		this.xmlHttp.send(this.params);
	} else {
		this.xmlHttp.setRequestHeader("X-Requested-With", "XmlHttpRequest");
		this.xmlHttp.setRequestHeader("Content-Type", this.requestMimeType);
		this.noCache();
		this.xmlHttp.send(null);
	}
}

Ajax.prototype.refresh = function() { this.open(); }

Ajax.prototype.callIframe = function()
{
	if($(this.ifrName) == null){
		var i = DOM.create("iframe",
		{
			id: this.ifrName,
			name: this.ifrName
		}
		);
		i.style.display = 'none';
		i.style.visibility = 'hidden';
		document.body.appendChild(i);
	}
	var p = (!empty(this.params)) ? this.params + "&" : "?" ;
	var l = location.pathname;
	if(this.url.indexOf("http://"))	this.url = "http://" + location.host + (l.substring(0,l.lastIndexOf("/"))) + "/" + this.url;
	var target = this.tempTarget ? this.tempTarget.id : this.target.id;
	if(!target) target = '';
	window[this.ifrName].location.href = this.baseUrl + "blank.htm" + p + "target=" + target + "&actionUrl=" + this.url;
};

Ajax.prototype.content = function(r) {
	this.clearGarbage();
	var t;
	if(this.tempTarget != null && this.tempTarget!='')
	{
		t = this.tempTarget;
		this.tempTarget = null;
	}
	else
		t = this.target;

	t.innerHTML = r[0];

	t.style.display = 'block';
	createScriptSrc(r[2]);
	createScriptBlock(r[1]);
	if(typeof this.parseForms=='function') this.parseForms(t);
	return true;
}
Ajax.prototype.clearGarbage = function() {
	$t('script').forEach(function(e) {
		if(!e.getAttribute('src'))
		e.parentNode.removeChild(e);
	});
}

/* fix call (no eval) */
Ajax.fixCall = Ajax.prototype.fixCall = function(r){
	var ini, add, code, _src = [], scriptIni, scriptEnd;
	ini = scriptEnd = 0
	add = code = "";

	while (ini!=-1){
		ini = r.indexOf('<script', ini);
		if (ini >=0){
			scriptIni = r.indexOf('>', ini) + 1;
			scriptEnd = r.indexOf('</script>', scriptIni);
			add = r.substring(scriptIni,scriptEnd);
			if(add.length==0) _src.push(scriptSrc(r.substring(ini, scriptIni)));
			else code += add;
			ini = scriptIni;
		}
	}
	var ret = [r, code, _src];
	ret['response'] = r;
	ret['code'] = code;
	ret['sources'] = _src;
	return ret;
}

/* keys dinamicas grato a www.lucasferreira.com */
Ajax.prototype.createInstance = function(){
	var key = Ajax._newKeyName();
	Ajax._instances[key] = this;
	return key;
}

Ajax.getInstance = function(key){
	return Ajax._instances[key];
}
Ajax._instances = [];
Ajax._newKeyName = function(){
	return ("AJAX_" + new Date().getTime());
}

Ajax.prototype.deleteInstance = function() {
	delete Ajax._instances[this.KEY];
}
/* */

var scriptSrc = function(src){
	var srcIni = src.indexOf('src="', src)+5;
	var srcEnd = src.indexOf('"', srcIni);
	return src.substring(srcIni, srcEnd);
}

var createScriptBlock = function(text){
	var s = DOM.create("script", { type: "text/javascript" });
	s.text = text;
	$t('head')[0].appendChild(s);
}

var createScriptSrc = function(_src) {
	var h = $t('head')[0];
	for(var i=0;i<_src.length;i++) {
		var s = DOM.create("script",
		{
			src: _src[i],
			type: "text/javascript",
			charset: "utf-8"
		});
		h.appendChild(s);
		s.onload = function() { bodyLoad.exec(bodyLoad.afterContent); bodyLoad.afterContent=[]; };
	}

}