/**
  * Transforma um mapa em uma String para ser usada em uma url
  * @param vars Array|Object Mapa de valores
  * @return String
  */
function urlEncode(vars) {
	var query = ""
	var first = true
	for(var i in vars) {
		if(first) {
			first = false
		}else{
			query += "&"
		}
		var key = escape(i)
		var value = escape(vars[i])
		query += key + "=" + value
	}
	return query
}

/**
 * Cria um objeto nativo XMLHttpRequest dependento do browser
 */
function HttpRequest() {
	try {
		return new ActiveXObject("Msxml2.XMLHTTP")
	} catch (e) {}

	try {
		return new ActiveXObject("Microsoft.XMLHTTP")
	} catch (e) {}

	try {
		return new XMLHttpRequest()
	} catch (e) {}

	return null
}

/**
 * classe Ajax
 */
function Ajax(url, onResult, onAbort) {
	this.url = new String(url == undefined ? "" : url)
	this.timeOutLimit = 15000
	this.timeOut = null
	this.request = null

	if (onAbort instanceof Function)
		this.onAbort = onAbort

	if (onResult instanceof Function)
		this.onResult = onResult

	this.clearParams()
	this.clearHeaders()
}

/**
 * Limpa os cabecalhos atribuidos
 */
Ajax.prototype.clearHeaders = function() {
	this.headers = {};
}

/**
 * Limpa os parametros atribuidos
 */
Ajax.prototype.clearParams = function() {
	this.params = {};
}

/**
 * virtual function que deve ser substituida por uma funcao customizada
 * @param req Objeto request
 * @param timer Objeto timer com o timestamp da requisicao, final e elapse
 */
Ajax.prototype.onResult = function(req, timer) {}
Ajax.prototype.onAbort = function(req, timer) {}

Ajax.prototype.setRequestHeader = function(name, value) {
	this.headers[name] = value
}

Ajax.prototype.setParam = function(name, value) {
	this.params[name] = value
}

Ajax.prototype.clearTimeOut = function() {
	if(this.timeOut)
		clearTimeout(this.timeOut)
	this.timeOut = null
}

Ajax.prototype.get = function() {
	this.abort()
	this.request = AJAX.get(this.url, this.onResult, this.params, this.headers)
	this.setTimeOut()
}

Ajax.prototype.post = function(data) {
	this.abort()
	data = data == undefined ? null : data
	this.request = AJAX.post(this.url, this.onResult, data, this.headers)
	this.setTimeOut()
}

Ajax.prototype.setTimeOut = function() {
	if(this.timeOutLimit > 0) {
		var parent = this
		this.timeOut = setTimeout(function() { parent.abort() }, this.timeOutLimit)
	}
}

Ajax.prototype.abort = function() {
	if(this.request && this.request.readyState != 4) {
		this.request.onreadystatechange = function(){};
		this.request.abort();
		this.onAbort()
		this.request = null;
	}
	this.clearTimeOut()
}

/**
 * Funcoes para uso estatico
 */
function AJAX() {}

AJAX.create = function(onResult, timer) {
	var req = new HttpRequest()
	timer = timer == undefined ? {} : timer
	timer.startTime = 0
	timer.stopTime = 0
	timer.elapsedTime = 0
	timer.toString = function() {
		return "[" + this.startTime + ", " + this.stopTime + ", " + this.elapsedTime + "]"
	}
	/*
	0 UNINITIALIZED open() has not been called yet.
	1 LOADING send() has not been called yet.
	2 LOADED send() has been called, headers and status are available.
	3 INTERACTIVE Downloading, responseText holds the partial data.
	4 COMPLETED Finished with all operations.
	*/
	req.onreadystatechange = function() {
		// status não existe no IE, até readyState for igual à 4
		try {
			if (req.readyState == 4 && req.status == 200) {
				timer.stopTime = new Date().getTime()
				timer.elapsedTime = timer.stopTime - timer.startTime
				if (onResult) onResult(req, timer)
			}
		} catch(e) {}
	}
	return req
}

AJAX.generateUID = function() {
	return "ajaxUID=" + new String(new Date().getTime()) + new String(Math.random())
}

AJAX.get = function(url, onResult , vars, headers) {
	var timer = {}
	var req = AJAX.create(onResult, timer)

	var query = urlEncode(vars)
	if (query != "") {
		url += "?" + query
	}

	timer.startTime = new Date().getTime()

	var uid = AJAX.generateUID();
	url += (url.indexOf("?") == -1) ? "?" + uid : "&" + uid

	req.open("GET", url, true)

	AJAX.setHeaders(req, headers) // precisa ser depois do open

	req.send(null)
	return req
}

AJAX.post = function(url, onResult, data, headers) {
	var timer = {}
	var req = AJAX.create(onResult, timer)

	timer.startTime = new Date().getTime()

	var uid = AJAX.generateUID();

//	url += (url.indexOf("?") == -1) ? "?" + uid : "&" + uid
	req.open("POST", url, true)

	AJAX.setHeaders(req, headers) // precisa ser depois do open

	timer.startTime = new Date().getTime()

	req.send(data)
	return req
}

AJAX.setHeaders = function(req, headers) {
	if (! headers) return false

	for(var name in headers) {
		var value = headers[name]
		req.setRequestHeader(name, value)
	}
	return true
}
