/**
*
* Librería AjaxLib v 1.0
*
* Realiza peticiones AJAX de manera sencilla y automática.constructor
*
*@author Maximiliano R. Firtman
*
* /

/** 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 petición
 * @param {Object} opciones Un objeto JSON con los atributos opcionales que queremos definirle
 * 
 * opciones disponibles:
 * 	id: un identificador interno para ser ecibido 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 elemento que queremos usar como cartel de "Cargando" mientras la petición se hace
 * 	onfinish: funcion a ejecutarse cuando se reciban los datos.Esta función recibira el Texto, JSON o XML recibido y el id de la peticion.
 * 	onerror: funcion a ejecutarse cuando se produzca error. Esta función recibe un objeto con detalles del error y el id de la petición.
 *  
 */ 
 function $Ajax(url, opciones) {
 	//preguntamos si no quiere cache
 	if(__$P(opciones,"cache",true)==false) {
 		//agregamos un parametro random a la URL
 		//Ponemos ? o & según 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 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 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 cartel de Cragando 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 paeticion si fue definido
 	var id = __$P(opciones, "id");
 	
 	if( funcionRetorno!=undefined ) {
 		//si el usuario indicó 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 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 Válido"} );
 						return;
 					}			
 					funcionRetorno(objeto, id);				
 		} 		
 	}
 } 

 /**
  * Funcion interna que se encaraga de prender o 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 la peticion desde Prototype
 */ 		 		
 function __$AjaxError(opciones, xhr, excepcion) {
 	//apagamos el cartel de caragando 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 de 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];
  		}
  	}
  }	
 		