/**
*
* Libreria AjaxLib v 1.0
* 
* Realiza peticiones AJAX de manera sencilla y automatica
*
*/


/** Especifica opciones de tipoRespuesta
*/
var $tipo = {
	XML: 0,
	TEXT: 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 realizara 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 o $tipo.XML
*   parametros: un string en formato URL o un objeto Hash
*   cache: true o false
*   avisoCargando: define el id de un elemneto que queremos usar como cartel de "Cargando"
*		   mientras la peticion se hace
*   onfinish: funcion a ejecutarse cuando se reciban los datos.
*   	      Esta funcion recibirá el texto, JSON o XML recibido
*	      y el id de la peticion.
*   onerror: funcion a ejecutarse cuando se produzca un error
*   	      Esta funcion recibirá un objeto con detalles del error
*	      y el id de la peticion.
*/

function $Ajax(url, opciones) {
	//Pregunta si no quiere cache
	if (__$P(opciones, "cache", true)==false) {
		// Agregamos un parametro 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 remplazado por otra libreria
	var protoOpc = {
		method: metodo,
		onSuccess: __$AjaxRecibir.bind(this, opciones),
		onExeption: __$AjaxError.bind(this, opciones),
		onFailure: __$AjaxError.bind(this, opciones)
	}	

	// Se 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 Prototype y ejecutar el evento onfinish de la peticion
*/

function __$AjaxRecibir(opciones, xhr) {
	// Si se ejecuta este metoso estamos seguros de que
	// readyState==4 y status ==200
	
	// Apagamos 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 pericion si fue definido
	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 evaluear 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 y apagar  el cartel
* de cargando, si existiera
*/

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 al peticion desde Prototype
*/

function __$AjaxError(opciones, xhr, excepcion) {
	//Apagamos el cartel de Cargando si existiera
	if (__$P(opciones, "avisioCargando") != undefined) {
		__$AjaxCargando(opciones.avisoCargando, false);
	}
	
	// Cuando se trate de un error del servidor, no hay exepcion
	if (excepcion==undefined){
		// Supongo error de HTTP, genero mensaje propio
		exepcion = {code: xhr.status, message:"Error del servidor"}
	}
	
	// Consulto si estaba definido el evento onerror
	var funcionError = __$P(opciones, "onerror");
	if (funcionError != undefined) {
		funcionError(exepcion, __$P(opciones, "id"));
	}
}

/**
* Funcion interna que se encarga de entregar en 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];
		}
	}
}

