GALILEO.util.Event.dateSelect = new YAHOO.util.CustomEvent("dateSelect");

/**
 * Particularizacion del calendario de YAHOO a un calendario propio
 * @param oConfig Objeto con la configuracion que debera poseer el caledario
 * Cada objeto de configuacion contiene los siguientes atributos:
 *  - id: Identificador que poseera el objeto calendario que vamos a crear.
 *  - containerId: Id del contenedor donde se mostrara nuestro objeto calendario.
 *  - inputEl: Elemento de texto donde se mostrara la fecha una vez que esta
 *             se ha seleccionado en el calendario
 *  - dateFormat: Formato que poseera la fecha del calendario.
 *                   dd: Indica que se deben mostrar los dias (Siempre en formato numerico)
 *                   MM: Indica que se deben mostrar meses (Siempre en formato numerico)
 *                   yy o yyyy: Si se desea que se muestren 2 o 4 cifras del anio
 *                Por defecto se establece el formato dd/MM/yyyy 
 *  - aId: Id del elemento que actua como lanzador del calendario
 *  - pathImgs: Objeto con los paths de las imagenes de limpieza y cierre que
 *              se asocian al calendario. Los atributos para este objeto son:
 *					- pathImgClear: Path de la imagen de limpieza
 *					- pathImgClose: Path de la imagen de cierre
 *              Si este objeto no es pasado se creara un calendario base
 * - navigator: Boolean que indica si el calendario posee seleccion de anio
 * - mindate: Fecha minima que se puede seleccionar
 * - maxdate: Fecha maxima que se puede seleccionar
 * @param title Titulo que desamos que posea el calendario
 **/
 
GALILEO.widget.GCalendar = function(oConfig, title) {
	if (oConfig.id && oConfig.containerId) {
		this._href = YAHOO.util.Dom.get(oConfig.aId);

		if (oConfig.inputEl) {
			this._inputEl = oConfig.inputEl;
		}
		this._container = document.createElement('div');
		this._container.className= 'gyui-calendar';
		this._container.id = oConfig.containerId;
		
		this._dateFormat = (oConfig.dateFormat) ? oConfig.dateFormat : 'dd/MM/yyyy';
		
		var pathImgs = GALILEO.widget.Calendar.config.pathImgs;
						
		if (pathImgs) {
			this._imgCloseSrc = pathImgs.pathImgClose;
			this._imgClearSrc = pathImgs.pathImgClear; 
			this._imgLeftNavSrc = pathImgs.pathImgLeftNav; 
			this._imgRightNavSrc = pathImgs.pathImgRightNav; 
		}

		document.body.appendChild(this._container);
		
		var mindate = (oConfig.mindate) ? oConfig.mindate : null;
		var maxdate = (oConfig.maxdate) ? oConfig.maxdate : null;
		
		this._reset = false;
		if (oConfig.pagedate || oConfig.selected) {
			this._reset = true;
		}
		var config = {
			pagedate: oConfig.pagedate,
			START_WEEKDAY: 1,
			title: title,
			close: true,
			iframe: true,
			selected: oConfig.selected,
			navigator: oConfig.navigator,
			mindate: mindate,
			maxdate: maxdate
		};
		
		GALILEO.widget.GCalendar.superclass.constructor.call(this, oConfig.id, this._container.id, config);
		
		if (this._href) {
			var showCalendar = function(e, obj) {
				obj.show();
			};
			YAHOO.util.Event.addListener(this._href, 'click', showCalendar, this);
		}
		
		this.selectEvent.subscribe(this._onSelectEvent, this, true);
		this.customConfig();
		
		this.renderEvent.subscribe(this._onRenderEvent, this, true);
		
		this.render();
		
		// Subcripcion al evento de redimensionado de la pagina
		var rePosition = function(e, obj) {
			var posicion = obj._calcPosition();
			if (posicion) {
				if (GALILEO.util.Navigator.getBrowser() == 'ie') {
					YAHOO.util.Dom.setStyle(obj._container, 'top', posicion[1]);
					YAHOO.util.Dom.setStyle(obj._container, 'left', posicion[0]);
				}
				else {
					YAHOO.util.Dom.setXY(obj._container, posicion);
				}
			}
		};
		
		YAHOO.util.Event.addListener(window, 'resize', rePosition, this);
	}
};

/**
 * Definicion de la herencia
 **/
YAHOO.extend(GALILEO.widget.GCalendar, YAHOO.widget.Calendar);

/**
 * Definicion de variables privadas para el calendario
 **/
GALILEO.widget.GCalendar._href = null;
GALILEO.widget.GCalendar.prototype._dateFormat = null;
GALILEO.widget.GCalendar._imgCloseSrc = null;
GALILEO.widget.GCalendar._imgClearSrc = null;
GALILEO.widget.GCalendar._imgLeftNavSrc = null; 
GALILEO.widget.GCalendar._imgRightNavSrc = null;
GALILEO.widget.GCalendar.prototype._reset = false;

// NOTA: Este contenedor hace referencia al contenedor general del calendario
GALILEO.widget.GCalendar._container = null;
/*
 * Almacena el input donde escribiremos la fecha
 */
GALILEO.widget.GCalendar._inputEl = null;

/**
 * Evento de redimension customizado
 */
GALILEO.widget.GCalendar.windowResizeEvent = new YAHOO.util.CustomEvent("windowResize");

GALILEO.widget.GCalendar.prototype._onSelectEvent = function(e, args, obj) {
	obj.updateDate();
	obj.hide();
};

GALILEO.widget.GCalendar.prototype._onRenderEvent = function(e, args, obj) {
	obj.configClear();
	obj.configNav();
};

/**
 * Metodo encargado de establecer la fecha establecida en el input asociado al calendario
 **/
GALILEO.widget.GCalendar.prototype.setDateFromInput = function() {

	if ((this._inputEl) && (this._inputEl.value.length > 0)) {
		var partes = this._dateFormat.split("/");
		var posiciones = new Array();
		
		if (partes.length === 3) {
			var expresion = "";
			for (var i = 0; i < partes.length; i++) {
				if (partes[i] === 'dd') {
					expresion += "(\\d{1,2})";
					posiciones['d'] = i + 1;
				} else if (partes[i] === 'MM'){
					expresion += "(\\d{2})";
					posiciones['m'] = i + 1;
				} else if (partes[i].indexOf("yy") != -1) {
					if (partes[i].indexOf("yyyy") != -1) {
						expresion += "(\\d{4})";
					} else {
						expresion += "(\\d{2})";
					}
					posiciones['y'] = i + 1;
				}
				if (i === 0 || i === 1) {
					expresion += "\\/";
				}
			}
		}
		
		var exp = new RegExp(expresion);
		if (exp.test(this._inputEl.value)) {
			var dia = this._inputEl.value.replace(exp, "$" + posiciones['d']);
			var mes = this._inputEl.value.replace(exp, "$" + posiciones['m']);
			var anio = this._inputEl.value.replace(exp, "$" + posiciones['y']);
			
			if (anio.lengh === 2) {
				// Consideramos el anio actual
				anio = '20' + anio;
			}
			
			this.select(mes + "/" + dia + "/" + anio);
			this.setYear(anio);			
			this.setMonth(mes - 1);
			
			this.render();
		}
	}
};

/*
 * Reescritura del metodo encargado de configurar el cierre del calendario
 */
GALILEO.widget.GCalendar.prototype.configClose = function(type, args, obj) {
	GALILEO.widget.GCalendar.superclass.configClose.call(this, type, args, obj);
	var imgClose = YAHOO.util.Dom.getElementsByClassName(YAHOO.widget.CalendarGroup.CSS_2UPCLOSE, "span", this.oDomContainer)[0];
	var style = 'url("' + this._imgCloseSrc + '") no-repeat';
	
	if (imgClose) {
		YAHOO.util.Dom.setStyle(imgClose, 'background', style);
	}
};
 
/*
 * Metodo encargado de establecer el icono de limpieza del calendario  
 */
GALILEO.widget.GCalendar.prototype.configClear = function() {

	var clearCalendar = function(e, obj) {
		if (obj._reset) {
			obj.reset();
		} else {
			obj.clear();
		}
		YAHOO.util.Event.stopEvent(e);
	};
	
	var linkClear = YAHOO.util.Dom.getElementsByClassName("link-clear", "a", this.oDomContainer)[0] || document.createElement("a");
	linkClear.href = "javascript:void(null);";
	linkClear.className = "link-clear";
	YAHOO.util.Event.addListener(linkClear, "click", clearCalendar, this, true);
	
	var imgClear = document.createElement('span');
	imgClear.className = "clear-icon calclear";
	linkClear.appendChild(imgClear);
	
	this.oDomContainer.appendChild(linkClear);
	
	var style = 'url("' + this._imgClearSrc + '") no-repeat';
	YAHOO.util.Dom.setStyle(imgClear, 'background', style);
}; 

/*
 * Metodo encargado de configurar las flechas de navegacion por los diferentes meses
 */
GALILEO.widget.GCalendar.prototype.configNav = function() {

	var navLeft  = YAHOO.util.Dom.getElementsByClassName(this.Style.CSS_NAV_LEFT, "a", this.oDomContainer)[0];
	var navRight = YAHOO.util.Dom.getElementsByClassName(this.Style.CSS_NAV_RIGHT, "a", this.oDomContainer)[0];

	var styleLeft  = 'url("' + this._imgLeftNavSrc  + '") no-repeat';
	var styleRight = 'url("' + this._imgRightNavSrc + '") no-repeat';

	YAHOO.util.Dom.setStyle(navLeft, 'background', styleLeft);
	YAHOO.util.Dom.setStyle(navRight, 'background', styleRight);
};

/*
 * Metodo privado encargado de establecer la posiciones de mostrado
 */
GALILEO.widget.GCalendar.prototype._calcPosition = function() {
	if (this._container && this._href) {
		var posicion = YAHOO.util.Dom.getXY(this._href);
		
		var extra = 5;
		if (isNaN(this._href.offsetHeight) === false) {
			extra = this._href.offsetHeight;
		}
		var bodyHeight = YAHOO.util.Dom.getClientHeight();
		var bodyWidth = YAHOO.util.Dom.getClientWidth();

		var containerHeight = this._container.clientHeight;
		var containerWidth = this._container.clientWidth;
		
		var posicionX = posicion[0];
		var posicionY = posicion[1] + extra + 1;

		if (posicionX + containerWidth > bodyWidth) {
			posicionX = posicionX - containerWidth + extra;
		}
		if (posicionY + containerHeight > bodyHeight) {
			posicionY = posicion[1] - containerHeight;
		}

		return [posicionX, posicionY];	
	}
	return false;
};

/**
 * Definicion del elemento encargado de mostrar un calendario
 **/
GALILEO.widget.GCalendar.prototype.show = function() {
	
	this.setDateFromInput();
	
	GALILEO.widget.GCalendar.superclass.show.call(this);

	var posicion = this._calcPosition();
	if (posicion) {
		if (GALILEO.util.Navigator.getBrowser() == 'ie') {
			YAHOO.util.Dom.setStyle(this._container, 'top', posicion[1]);
			YAHOO.util.Dom.setStyle(this._container, 'left', posicion[0]);
		}
		else {
			YAHOO.util.Dom.setXY(this._container, posicion);
		}
	}
};

/**
 * Definicion del metodo encargado de realizar un reseteo de las fechas
 **/
GALILEO.widget.GCalendar.prototype.clear = function() {
	GALILEO.widget.GCalendar.superclass.clear.call(this);
	/*this.configClear();
	this.configNav();*/
	if (this._inputEl) {
		this._inputEl.value = "";
	}
};

/*
 * Redefinicion del metodo reset
 */
GALILEO.widget.GCalendar.prototype.reset = function() {
	GALILEO.widget.GCalendar.superclass.reset.call(this);
	/*this.configClear();
	this.configNav();*/
	if (this._inputEl) {
		this._inputEl.value = "";
	}
};

GALILEO.widget.GCalendar.prototype.setDateFormat = function(format) {

	this._dateFormat = format;
};

/**
 * Definicion del metodo encargado de establecer la fecha en el text
 **/
GALILEO.widget.GCalendar.prototype.updateDate = function() {
	var fecha = this.getSelectedDates()[0];
	if (fecha) {
		var dia  = fecha.getDate();
		var mes = fecha.getMonth() + 1;
		if (dia < 10) {
			dia = "0" + dia;
		}
		if (mes < 10) {
			mes = "0" + mes;
		}
		var ano = fecha.getYear();
		if ((GALILEO.util.Navigator.getBrowser() != 'ie') || ((GALILEO.util.Navigator.getBrowser() == 'ie') && (ano < 2000))) {
			ano = ano + 1900;
		}
		GALILEO.util.Event.dateSelect.fire(this._container.id, dia, mes, ano);
		
		if (this._inputEl) {
			var expDias  = /dd/g;
			var expMeses = /MM/g;
			var expAnios = /yy/g;
			if (this._dateFormat.indexOf('yyyy') != -1) {
				expAnios =  /yyyy/g;
			}
			
			var formatoFecha = this._dateFormat;
			formatoFecha = formatoFecha.replace(expDias, dia);
			formatoFecha = formatoFecha.replace(expMeses, mes);
			formatoFecha = formatoFecha.replace(expAnios, ano);
			
			this._inputEl.value = formatoFecha;
		}
	}
};

/*
 * Reescritura del metodo de configuracion para establecer el locale a Espanol
 */
GALILEO.widget.GCalendar.prototype.customConfig = function(){ 
    this.cfg.setProperty("MONTHS_SHORT", ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"]); 
    this.cfg.setProperty("MONTHS_LONG", ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]); 
    this.cfg.setProperty("WEEKDAYS_1CHAR", ["D", "L", "M", "X", "J", "V", "S"]); 
    this.cfg.setProperty("WEEKDAYS_SHORT", ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"]); 
    this.cfg.setProperty("WEEKDAYS_MEDIUM", ["Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"]); 
    this.cfg.setProperty("WEEKDAYS_LONG", ["Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado"]); 	 
};

/*
 * Redefinicion del evento de navegacion
 */
GALILEO.widget.GCalendar.prototype.onChangePage = function() {
	GALILEO.widget.GCalendar.superclass.onChangePage.call(this);
	/*this.configClear();
	this.configNav();*/
};

/*
 * Calendario con la posiblidad de seleccion de anio
 * @see GALILEO.widget.GCalendar
 */
GALILEO.widget.GCalendarYear = function(oConfig) {
	if (oConfig.id && oConfig.containerId) {
		var title = "A&ntilde;o: "; 
		GALILEO.widget.GCalendarYear.superclass.constructor.call(this, oConfig, title);
		
		YAHOO.util.Dom.addClass(this.oDomContainer, 'gyui-calendar-year');
		
		this.configInput();		
		this._year = this.today.getFullYear();
	}
};

/**
 * Definicion de la herencia
 **/
YAHOO.extend(GALILEO.widget.GCalendarYear, GALILEO.widget.GCalendar);

/*
 * Definicion del elemento de seleccion para el calendario
 */
GALILEO.widget.GCalendarYear.prototype._input = null;

/*
 * Definicion de una variable que almacena el anio actual
 */
GALILEO.widget.GCalendarYear._year = null;

/*
 * Metodo encargado de configurar el input de seleccion de anio
 */
GALILEO.widget.GCalendarYear.prototype.configInput = function() {
	var input = GALILEO.util.Dom.createElement('input', [{name: 'type', value: 'text'},
														 {name: 'name', value: 'input-year'},
														 {name: 'id', value:'input-change-year'},
														 {name: 'size', value: '4'},
														 {name: 'maxlength', value: '4'},
														 {name: 'value', value: ''}]);
	var titulo = YAHOO.util.Dom.getElementsByClassName('title', 'div', this.oDomContainer)[0];
	
	if (titulo) {
		titulo.appendChild(input);
		this._input = input;
		YAHOO.util.Event.addListener(this._input, "keyup", this.regenerateCalendar, this);
	}
};

/*
 * Callback utilizado para la regeneracion del calendario ante una seleccion de anio
 */
GALILEO.widget.GCalendarYear.prototype.regenerateCalendar = function(e, obj) {
	obj.recreateCalendar();
	obj.configClear();
	obj.configNav();
};

/*
 * Metodo encargado de realizar los calculos necesarios para la regeneracion del calendario
 */
GALILEO.widget.GCalendarYear.prototype.recreateCalendar = function() {
	if (this._input.value.length == 4) {
		if (GALILEO.util.String.isInt(this._input.value)) {
			var regenerarInput = false;
			if (this._input.value < this._year) {
				var resta = this._year - this._input.value;
				this._year = this._input.value;
				this.subtractYears(resta);
				regenerarInput = true;
			}
			else if (this._input.value > this._year) {
				var suma =  this._input.value - this._year;
				this._year = this._input.value;
				this.addYears(suma);
				regenerarInput = true;
			}
				
			if (regenerarInput === false) {
				this._year = this._input.value;
				this._input.value = "";
			}
		}
	}
};

/*
 * Redefinicion del metodo encargado de realizar la limpieza del calendario
 */
GALILEO.widget.GCalendarYear.prototype.clear = function() {
	GALILEO.widget.GCalendarYear.superclass.clear.call(this);
	this._year = this.today.getFullYear();
	this.configInput();
};

/*
 * Redefinicion del metodo encargado de realizar un reset sobre el calendario
 */
GALILEO.widget.GCalendarYear.prototype.reset = function() {
	GALILEO.widget.GCalendarYear.superclass.reset.call(this);
	this._year = this.today.getFullYear();
	this.configInput();
};

/*
 * Redefinicion del metodo encargado de ocultar un calendario
 */
GALILEO.widget.GCalendarYear.prototype.hide = function() {
	if (this._input) {
		this._input.value = "";
	}
	GALILEO.widget.GCalendarYear.superclass.hide.call(this);
};

/*
 * Redefinicion del evento de navegacion
 */
GALILEO.widget.GCalendarYear.prototype.onChangePage = function() {
	GALILEO.widget.GCalendarYear.superclass.onChangePage.call(this);
	this._year = this.cfg.getProperty("pagedate").getFullYear();
	this.configInput();
};
