/**
 * calendarized(), tooltip();
 * 
 * Archivo que crea un calendario (con jCalendar) y tooltips en �l, mostrando eventos destacados, 
 * a partir de un listado de eventos. 
 * Autor: David Prados Luna (dprados@oesia.com)
 * Versi�n: 0.1 (15 Octubre 2010)
 * Descripci�n:
 * - Toma 1 argumento opcional.
 *   1. Opciones. Esto es un objeto json y permite las siguientes opciones (valores por defecto):
 *       - eventType: ['click'] //Array de eventos. No implementado en esta versi�n.
 *		- removeBeforeComplete: true // si es true, una vez termina de cargar el componente dise�ado con eventos del listado por defecto, eliminar� dicho listado.
 *		- calendar: {
 *	        - dateSeparator: " de "
 *			- complete: // Callback no implemetado en esta versi�n.
 *			- days: ['D','L','M','X','J','V','S'] // Locale.
 *			- months: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'] // Locale
 *			- navLinks: {p:'Anterior', n:'Siguiente', c:'Cerrar', b:'Seleccione una fecha', t: 'Hoy'} //Locale
 *			- jumpDate: false // Si es true, mostrar� unos selects para ir a fechas concretas.
 */

function calendarized(){}
jQuery(function($){
	calendarized.prototype = {
		schedule: null,
		calendar: null,
		jCalendar: null,
		scheduleList: {},
		scheduleTree: {},
		calendarNav: null,
		targets: [],
		settings: {
			'eventType': ['click'],
			removeBeforeComplete: true,
			calendar: {
				dateSeparator: " de ",
				complete: function(){
					this.setEvents();
				},
				days: ['D','L','M','X','J','V','S'],
				months: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
				navLinks: {p:'Anterior', n:'Siguiente', c:'Cerrar', b:'Seleccione una fecha', t: 'Hoy'},
				jumpDate: false
			}
		},
		init: function(selector, options){
			this.schedule = $(selector);
			$.extend(true, this.settings, options);
			this.jCalendar = jQuery.jcalendar;
			this.setShedule();
			this.buildCalendar();
			this.fire();
			return this;
		},
		fire: function(e){
			this.calendar.delegate("td:has(ul) > a", 'click', function(e){ tooltip.fire(e); return false;});
		},
		setShedule: function(){
			var events = this.schedule.find("li > p"),
				date = null,
				content = null;
			for(var i=0;i<events.length; i++){
				date = $(events[i]).find("span.datetime").text();
				if(!this.scheduleList[date])
					this.scheduleList[date] = [];
				content = $(events[i]).clone();
				content.find("span.datetime").remove();
				this.scheduleList[date].push(content[0]);
			}
		},
		buildCalendar: function(){
			var opts = this.binding(this.settings.calendar);
			this.calendar = $(this.schedule).jcalendar(opts);
		},
	
		setEvents: function(){
			var calendarDays = this.calendar.find("td > a"),
				separator = this.settings.calendar.dateSeparator,
				months = this.settings.calendar.months;
			for(var event in this.scheduleList){
				var foundDay = calendarDays.filter(function(){
					var month = $(this).attr("datetime").split(separator)[1],
						numMonth = months.index(month);
					return $(this).attr("datetime").split(separator).join("/").replace(month, numMonth) == event;
				});
				this.addScheduleEvent(foundDay.parent(), this.scheduleList[event]);
			}
			if(this.settings.removeBeforeComplete)
				this.schedule.remove();
		},
		addScheduleEvent: function(day, scheduleEvent){
			var scheduleEventLen = scheduleEvent.length,
				list = $("<ul>");
			for(var i=0; i<scheduleEventLen; i++)
				$("<li>", { html: scheduleEvent[i]}).appendTo(list);
			day.addClass("eventDay");
			day.append(list);
		},
		binding: function(bindObject){
			for(var prop in bindObject){
				if (typeof bindObject[prop] == "function")
					bindObject[prop] = bindObject[prop].bind(this);
			}
			return bindObject;
		}
	};
	
	var tooltip = {
		hasMouseup: false,
		fire: function(event){
			$(".tooltip").live("mouseleave", $.proxy(this.hideEvent, this));
			this.show(event);
		},
		show: function(e){
			var e = e || window.Event,
				target = e.target || e.srcElement;
			this.computeTooltip(target);
			this.computeTimeout(target);
			$("body").one("mouseover", $.proxy(this.checkPosition, this));
			
			return false;
		},
		computeTooltip: function(source){
			var eventsShedule = $(source).parent().children("ul").clone(true),
				tooltipContent = $("<div class='tooltipContent'>").css({
					"-moz-border-radius": "5px",
					"-webkit-border-radius": "5px",
					"border-radius": "5px",
					"-moz-box-shadow": "1px 1px 5px #DBDBDB",
					"-webkit-box-shadow": "1px 1px 5px #DBDBDB",
					"box-shadow": "1px 1px 5px #DBDBDB"
				}),
				tooltipHeader = $("<strong class='tooltipHeader'>Eventos para este día:</strong>"),
				wrapper = $("<div>", {'class':'tooltip'}).css({
					top: $(source).offset().top+$(source).height(),
					left: $(source).offset().left-$(source).width()/2,
					"display": "none"
				}).append(tooltipHeader, tooltipContent);
			tooltipContent.append(eventsShedule);
			$("body").prepend(wrapper);
			wrapper.fadeIn();
		},
		computeTimeout: function(target){
			window.setTimeout($.proxy(function(){
				if(!this.hasMouseup)
					this.hideEvent(target);
			}, this), 5000);
		},
		hideEvent: function(e){
			var e = e || window.event,
				target = e.target || e.srcElement;
			window.setTimeout($.proxy(function(){
				$(".tooltip").fadeOut(function(){$(this).remove();});
				this.hasMouseup = 0;
			}, this),4*600);
			//$("body").unbind('mouseover');
		},
		checkPosition: function(e){
			var e = e || e.event,
				related = e.relatedTarget || (e.toElement !== undefined ? e.toElement : e.fomElement),
				target = e.target || e.srcElement;
			if ($(target).hasClass("tooltip") || $(target).closest(".tooltip").length) {
				this.hasMouseup = 1;
			}
			
		}
	};
	jQuery.fn.calendarized = function(options){
		var options = options || {};
		if($(this).length)
			new calendarized().init(this.selector, options);
		return this;
	};
});
