/**
*
* Libreria Ajaxlib v 1.0
*
*/

/* Especifica opciones para tipoRespuesta */
var $tipo = {
	XML : 0,
	TEXTO: 1,
	JSON: 2
}

/* Especifica opciones para método */

var $metodo = {
	GET: "GET",
	POST: "POST"
}

/**
* Realiza un nuevo requerimiento AJAX a la url especificada con las opciones definidas
*@param {String} url. La URL donde realizar la peticion
*@param {Object} opciones. Un objeto JSON con los atributos opcionales
*que queremos definirle.
*
*opciones disponibles:
*	id: Un identificador interno para ser recibido junto a los datos.
*	metodo: $metodo.POST o $metodo.GET
*	tipoRespuesta: $tipo.TEXT, $tipo.JSON o $tipo.XML
*	parametros:un string en formato URL o un objeto Hash
*				cache: true o false
*	avisoCargando: define el id de un elemento que queremos usar como cartel de "Cargando"
*					mientras la peticion se hace
*	onfinish: funcion a ejecutarse cuando se reciban los datos.
*				Esta funcion recibira el Texto, JSON o XML recibido y el id de la peticion.
*/

function $Ajax(url,opciones){
		// Preguntamos si no quiere Caché
		if (__$P(opciones, "cache", true)==false){
				 //Agregamos un parámetro random a la URL
				 //Ponemos ? o & segun la presencia de parámetros anteriores
				 var caracter = "?";
				 if (url.indexOf("?") > 0){ 
				 	caracter = "&";
					url += caracter + Math.random();
				 }
		}
		
		var metodo = __$P(opciones, "metodo", $metodo.GET);
		var parametros = __$P(opciones, "parametros");
		
		//Genera JSON de propiedades necesarias para Prototype
		//En un futuro puede ser reemplazado por otra librería
		var protoOpc = {
			method: metodo,
			onSuccess: __$AjaxRecibir.bind(this, opciones),
			onException: __$AjaxError.bind(this, opciones),
			onFailure: __$AjaxError.bind(this,opciones)
		}
		
		///Si se definieron los parámetros los agregamo
		if (parametros!=undefined){
			protoOpc.parameters = parametros;
		}
		
		//Genera la nueva peticion vía Prototype
		var peticion = new Ajax.Request(url,protoOpc);
		
		//Prende el cartel Cargando, si existiera
		if (__$P(opciones,"avisoCargando") !=undefined){
			__$AjaxCargando(opciones.avisoCargando, true);
		}
}

/**
* Funcion interna que se encarga de recibir la peticion lista desde Prototype
* y ejecutar el evento onfinish de la peticion
*/

function __$AjaxRecibir(opciones, xhr){
	// Si se ejecuta este metodo estamos seguros de que readyState==4 y status==200
	
	//Apagamos el cartel de Cargando si existiera
	if (__$P(opciones, "avisoCargando")!=undefined){
		__$AjaxCargando(opciones.avisoCargando, false);
	}
	
	//Traemos la funcion onfinish si fue definida
	var funcionRetorno = __$P(opciones, "onfinish");
	//Traemos el identificador de la peticion se fue definido
	var id = __$P(opciones, "id");
	
	if (funcionRetorno!= undefined){
		//Si el usuario indico que quiere recibir la respuesta
		//Supongo TEXTO como tipo por defecto.
		var tipoRespuesta = __$P(opciones, "tipoRespuesta",$tipo.TEXTO);
		switch(tipoRespuesta){
			case $tipo.TEXTO:
					funcionRetorno(xhr.responseText, id);
					break;
			case $tipo.XML:
				funcionRetorno(xhr.responseXML, id);
				break;
			case $tipo.JSON:
				//Intentamos evaluar el JSON por si no es valido
				var objeto;
				try{
					objeto = xhr.responseText.evalJSON();
				} catch(e){
					__$AjaxError(opciones, xhr,{code: -1, message: "JSON No Valido" });
					return;
				}
				funcionRetorno(objeto, id);
		}
	}
}

/**
* Funcion interna que se encarga de prender o apagar el cartel de Cargando, si existira
*/

function __$AjaxCargando(cartel,prender){
	if (prender){
		$(cartel).show();
	}else{
		$(cartel).hide();
	}
}

/**
* Funcion interna que se encarga de recibir la ejecucion
* cuando se produzca algun error en la peticion desde Prototype
*/
function __$AjaxError(opciones, xhr, excepcion){
	// Apagamos cartel de Cargando si existiera
	if (__$P(opciones, "avisoCargando")!=undefined){
		__$AjaxCargando(opciones.avisoCargando, false);
	}
	
	//Cuando se trata de un error de servidor, no hay excepcion
	if (excepcion==undefined){
		//Supongo error de HTTP, genero mensaje propio
		excepcion = { code: xhr.status, message: "Error del servidor"};
	}
	
	//Consulto si estaba definido el evento onerror
	var funcionError = __$P(opciones, "onerror");
	if (funcionError!=undefined){
		funcionError(excepcion, __$P(opciones, "id"));
	}
}

/**
* Funcion interna que se encarga de entregar un parámetro opcional
* desde una coleccion tipo JSON, con un valor por defecto
*/

function __$P(coleccion, parametro, defecto){
	if (coleccion==undefined){
		return defecto;
	} else {
		if (coleccion[parametro]==undefined){
			return defecto;
		} else {
			return coleccion[parametro];
		}
	}
}
