// JavaScript Document
/**
*
*	Libreria AjaxLib V 1.0
*
*	Realiza peticiones Ajax de manera sencilla y automática
*
*	@author Maximiliano R. Firtman firt@itmaster.es
*
*/


/** Especifica opciones para tipoRespuesta
 */

var $tipo = {
	XML: 0,
	TEXTO: 1,
	JSON: 2
}

var $metodo = {
	GET: "GET",
	POST: "POST"
}

/**
 *	Realiza un requerimiento AJAX a la url especificada
 *	Con las opciones definidas
 *	@param { String } url de 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.TEXTO, $tipo.JSON ó $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: función a ejecutarse cuando se reciban los datos. Esta función recibirá el Texto, Json o XML recibido y el id de la peticion.
 *		onerror: funcion a ejecutarse cuando se produzca un error. Esta función recibe un objeto con detalles del error 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 parametros 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 eemplazado por otra libreria
	
	var protoOpc = {
		method: metodo,
		onSuccess: __$AjaxRecibir.bind(this, opciones),
		onException: __$AjaxError.bind(this, opciones),
		onFailure: __$AjaxError.bind(this, opciones)
	
	}
	
	//Si se definieron los parametros los agregamos
	if (parametros != undefined){
		protoOpc.parameters = parametros;
	}
	
	//Genera la nueva peticion via Prototype
	var peticion = new Ajax.Request(url, protoOpc);
	
	//Prende el cartel de Cargando, si existiera
	if (__$P(opciones, "avisoCargando") != undefined){
		__$AjaxCargando(opciones.avisoCargando, true);	
	}
}

/**
 *	Funcion interna que se encarga de recibir la peticion lista desde el 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 si fue detenido
	var id = __$P(opciones, "id");
	
	if (funcionRetorno != undefined){
		//Si el usuario indico que quiere recibir la respuesta Suponemos 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 validar 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 exisitiera
*/

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 parametro 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];
		}
	}
}