/**
 * class	HDF_Calendar
 * author	Paul Kruijt
 */
var HDF_Calendar = new Class({
	
	/**
	 * initialize
	 * @return	void
	 */
	initialize: function(current_date_day)
	{
		// nodes
		this.document_node			= document.getElement('body');
		this.root_node				= $('calendar');
		this.title_node				= $('calendar_title');
		this.subtitle_node			= $('calendar_subtitle');
		this.filter_node			= $('calendar_filter');
		this.filter_see_node		= $('calendar_filter_see');
		this.filter_do_node			= $('calendar_filter_do');
		this.filter_exp_node		= $('calendar_filter_exp');
		this.previous_day_node		= $('calendar_previous_day');
		this.next_day_node			= $('calendar_next_day');
		this.view_switch_node		= $('calendar_view_switch');
		this.content_wrapper_node	= $('calendar_content_wrapper');
		this.content_events_node	= $('calendar_content_events');
		this.content_node			= $('calendar_content');
		this.cursor_x_node			= $('calendar_cursor_x');
		this.cursor_y_node			= $('calendar_cursor_y');
		this.content_empty_node		= $('calendar_content_empty');
		this.button_previous_node	= $('calendar_button_previous');
		this.button_next_node		= $('calendar_button_next');
		this.content_month_node		= $('calendar_content_month');
		this.content_day_node		= $('calendar_content_day');
		this.content_day_times_node	= $('calendar_content_day_times');
		this.blocker_node			= $('calendar_blocker');
		this.debugger_node			= $('calendar_debugger');
		
		// id's
		this.blocker_id				= 'calendar_blocker';
		this.content_id				= 'calendar_content';
		this.content_events_id		= 'calendar_content_events';
		this.content_month_id		= 'calendar_content_month';
		this.content_day_id			= 'calendar_content_day';
		this.content_day_times_id	= 'calendar_content_day_times';
		this.event_popup_id			= 'calendar_event_popup';
		this.event_popup_img_id		= 'calendar_event_popup_img';
		this.event_popup_txt_id		= 'calendar_event_popup_txt';
		this.event_popup_close_id	= 'calendar_event_popup_close';
		this.event_popup_loader_id	= 'calendar_event_popup_loader';
		this.content_loader_id		= 'calendar_content_loader';
		this.button_previous_id		= 'calendar_button_previous';
		this.button_next_id			= 'calendar_button_next';
		this.content_day_events_id	= 'calendar_content_day_events';
		this.filter_id				= 'calendar_filter';
		this.previous_day_id		= 'calendar_previous_day';
		this.next_day_id			= 'calendar_next_day';
		this.zoom_in_id				= 'calendar_zoom_in';
		this.zoom_out_id			= 'calendar_zoom_out';
		this.time_left_id			= 'calendar_content_day_time_left';
		this.time_right_id			= 'calendar_content_day_time_right';
		this.time_first_id			= 'calendar_content_day_time_first';
		this.time_last_id			= 'calendar_content_day_time_last';
		this.cursor_x_id			= 'calendar_cursor_x';
		this.cursor_y_id			= 'calendar_cursor_y';
		this.view_switch_id			= 'calendar_view_switch';
		
		// classes
		this.hide_class						= 'hide';
		this.show_class						= 'show';
		this.visible_class					= 'visible';
		this.hidden_class					= 'hidden';
		this.active_class					= 'active';
		this.in_active_class				= 'in_active';
		this.filters_class					= 'calendar_filters';
		this.zoom_in_class					= 'calendar_zoom_in';
		this.zoom_out_class					= 'calendar_zoom_out';
		this.zoom_in_disabled_class			= 'calendar_zoom_in_disabled';
		this.zoom_out_disabled_class		= 'calendar_zoom_out_disabled';
		this.content_event_class			= 'calendar_content_event';
		this.content_day_class				= 'calendar_content_day';
		this.content_day_zoomed_class		= 'calendar_content_day_zoomed';
		this.content_day_times_class		= 'calendar_content_day_times';
		this.content_day_times_zoomed_class	= 'calendar_content_day_times_zoomed';
		this.filter_empty_class				= 'calendar_filter_empty';
		
		// prefix
		this.cell_prefix				= 'calendar_column_';
		this.date_prefix				= 'date_';
		this.content_day_event_prefix	= 'calendar_content_day_event_';
		this.filter_prefix				= 'calendar_filter_';
		
		// http
		this.location_url				= '../modules/festival/festival_calendar_location.php';
		this.month_url					= '../modules/festival/festival_calendar_month.php';
		this.day_url					= '../modules/festival/festival_calendar_day.php';
		this.event_type_session_url		= '../modules/festival/festival_event_type_session.php';
		this.loader_url					= '../img/loader.gif';
		
		// settings
		this.current_date_day		= current_date_day;
		this.month_header_height	= 40;
		this.slider_duration		= 2000;
		this.fader_duration			= 1000;
	},
	
	/**
	 * start
	 * @return void
	 */
	start: function()
	{
		// load month content
		this.loadMonthContent();
	},
	
	/**
	 * set dimensions of content node
	 * @return void
	 */
	setContentDimensions: function()
	{
		var content_node		= $(this.content_id);
		var content_month_node	= $(this.content_month_id);
		var content_day_node	= $(this.content_day_id);
		
		if (content_month_node)
		{
			var content_month_coordinates	= content_month_node.getCoordinates();
			var content_month_height		= content_month_coordinates.height.toInt();
			
			// set height
			content_node.setStyle('height', content_month_height+'px');
		}
		
		if (content_day_node)
		{
			var content_day_coordinates	= content_day_node.getCoordinates();
			var content_day_height		= content_day_coordinates.height.toInt();
			
			// set height
			content_node.setStyle('height', content_day_height+'px');
		}
	},
	
	/**
	 * set events
	 * @return void
	 */
	setEvents: function()
	{
		// filter events
		this.setFilterEvents();
		
		// header events
		this.setHeaderEvents();
		
		// cursor events
		this.setCursorEvents();
		
		// hover events
		this.setHoverEvents();
		
		// scroll events
		this.setScrollEvents();
		
		// view switch events
		this.setViewSwitchEvents();
	},
	
	/**
	 * set filter events
	 * @return	void
	 */
	setFilterEvents: function()
	{
		var _this		= this;
		var filter_node	= $(this.filter_id);
		
		var checkbox_nodes			= filter_node.getElements('a');
		var total_checkbox_nodes	= checkbox_nodes.length;
		
		if (total_checkbox_nodes > 0)
		{
			checkbox_nodes.each(function(checkbox_node)
			{
				checkbox_node.removeEvents();
				
				checkbox_node.addEvents(
				{
					'click' : function()
					{
						var filter_class	= this.get('class') == _this.in_active_class ? '' : _this.in_active_class;
						var display_class	= this.get('class') == _this.in_active_class ? 'block' : 'none';
						
						// (un)check box
						this.set('class', filter_class);
						
						// filter
						_this.filter(this, display_class);
						
						// set event type sessions
						_this.setEventTypeSessions();
						
						return false;
					}
				});
			});
		}
	},
	
	/**
	 * set day filter events
	 * @return	void
	 */
	setDayFilterEvents: function()
	{
		var _this = this;
		
		var filter_node				= $(this.filter_id);
		var checkbox_nodes			= filter_node.getElements('a');
		var total_checkbox_nodes	= checkbox_nodes.length;
		
		if (total_checkbox_nodes > 0)
		{
			checkbox_nodes.each(function(checkbox_node)
			{
				checkbox_node.removeEvents();
				
				checkbox_node.addEvents(
				{
					'click' : function()
					{
						var filter_class	= this.get('class') == _this.in_active_class ? '' : _this.in_active_class;
						var display_class	= this.get('class') == _this.in_active_class ? 'block' : 'none';
						
						// (un)check box
						this.set('class', filter_class);
						
						// filter
						_this.filterDayContent(this, display_class);
						
						// set event type sessions
						_this.setEventTypeSessions();
						
						return false;
					}
				});
			});
		}
	},
	
	/**
	 * set day navigate events
	 * @return	void
	 */
	setDayNavigateEvents: function()
	{
		var _this				= this;
		var previous_day_node	= $(this.previous_day_id);
		var next_day_node		= $(this.next_day_id);
		
		if (previous_day_node)
		{
			previous_day_node.removeEvents();
			
			previous_day_node.addEvent('click', function()
			{
				var date_day = this.get('class').replace(_this.date_prefix, '').toInt();
				
				// set private current day
				_this.current_date_day = date_day;
				
				// load day content
				_this.loadDayContent(date_day);
				
				return false;
			});
		}
		
		if (next_day_node)
		{
			next_day_node.removeEvents();
			
			next_day_node.addEvent('click', function()
			{
				var date_day = this.get('class').replace(_this.date_prefix, '').toInt();
				
				// set private current day
				_this.current_date_day = date_day;
				
				// load day content
				_this.loadDayContent(date_day);
				
				return false;
			});
		}
	},
	
	/**
	 * set day zoom events
	 * @return	void
	 */
	setDayZoomEvents: function()
	{
		var _this					= this;
		var zoom_in_node			= $(this.zoom_in_id);
		var zoom_out_node			= $(this.zoom_out_id);
		var content_day_node		= $(this.content_day_id);
		var content_day_times_node	= $(this.content_day_times_id);
		var button_previous_node	= $(this.button_previous_id);
		var button_next_node		= $(this.button_next_id);
		
		if (zoom_in_node)
		{
			zoom_in_node.removeEvents();
			
			zoom_in_node.addEvent('click', function()
			{
				var zoom_class = this.get('class');
				
				if (zoom_class == _this.zoom_in_class)
				{
					// load day content
					_this.loadDayContent(_this.current_date_day, 1);
				}
				
				return false;
			});
		}
		
		if (zoom_out_node)
		{
			zoom_out_node.removeEvents();
			
			zoom_out_node.addEvent('click', function()
			{
				var zoom_class = this.get('class');
				
				if (zoom_class == _this.zoom_out_class)
				{
					// load day content
					_this.loadDayContent(_this.current_date_day);
				}
				
				return false;
			});
		}
	},
	
	/**
	 * set header events
	 * @return	void
	 */
	setHeaderEvents: function()
	{
		var _this				= this;
		var content_month_node	= $(this.content_month_id);
		
		if (content_month_node)
		{
			var th_nodes		= content_month_node.getElements('th');
			var total_th_nodes	= th_nodes.length;
			
			if (total_th_nodes > 0)
			{
				th_nodes.each(function(th_node)
				{
					var anchor_node = th_node.getElement('a');
					
					if (anchor_node)
					{
						anchor_node.removeEvents();
						
						anchor_node.addEvents(
						{
							'click' : function()
							{
								var date_day = this.id.replace(_this.date_prefix, '').toInt();
								
								// set private current day
								_this.current_date_day = date_day;
								
								// load day content
								_this.loadDayContent(date_day);
								
								return false;
							}
						});
					}
				});
			}
		}
	},
	
	/**
	 * load month content
	 * @param	integer	date_day
	 * @return	void
	 */
	loadMonthContent: function()
	{
		if (this.current_date_day > 0)
		{
			// set vars
			var _this	= this;
			
			// loader
			var http_request = new Request({
				url:		this.month_url,
				method:		'get',
				data:		'date_day='+this.current_date_day,
				onRequest:	function()
				{
					// show blocker
					_this.blocker_node.set('class', _this.show_class);
					
					// create loader
					_this.createContentLoader();
				},
				onSuccess:	function(month_content)
				{
					// hide blocker
					_this.blocker_node.set('class', _this.hide_class);
					
					// remove loader
					_this.removeContentLoader();
					
					// create content
					_this.createMonthContent(month_content);
				}
			});
			
			http_request.send();
		}
	},
	
	/**
	 * load day content
	 * @param	integer	date_day
	 * @return	void
	 */
	loadDayContent: function(date_day, zoomed)
	{
		var date_day	= date_day.toInt();
		var zoomed		= zoomed ? 1 : 0;
		
		if (date_day > 0)
		{
			// set vars
			var _this	= this;
			
			// loader
			var http_request = new Request({
				url:		this.day_url,
				method:		'get',
				data:		'date_day='+date_day+'&zoomed='+zoomed,
				onRequest:	function()
				{
					// show blocker
					_this.blocker_node.set('class', _this.show_class);
					
					// create loader
					_this.createContentLoader();
				},
				onSuccess:	function(day_content)
				{
					// hide blocker
					_this.blocker_node.set('class', _this.hide_class);
					
					// remove loader
					_this.removeContentLoader();
					
					// create content
					_this.createDayContent(day_content);
				}
			});
			
			http_request.send();
		}
	},
	
	/**
	 * set cursor events
	 * @return	void
	 */
	setCursorEvents: function()
	{
		var _this			= this;
		var content_node	= $(this.content_id);
		var cursor_x_node	= $(this.cursor_x_id);
		var cursor_y_node	= $(this.cursor_y_id);
		
		if (content_node && cursor_x_node && cursor_y_node)
		{
			content_node.removeEvents();
			
			content_node.addEvents(
			{
				'mouseleave' : function()
				{
					cursor_x_node.set('class', _this.hide_class);
					cursor_y_node.set('class', _this.hide_class);
				},
				
				'mousemove' : function(e)
				{
					var window_scroll	= window.getScroll();
					var mouse_x			= ((e.client.x - this.getPosition().x) + window_scroll.x).toInt();
					var mouse_y			= ((e.client.y - this.getPosition().y) + window_scroll.y).toInt();
					
					if (mouse_y > _this.month_header_height)
					{
						// set new position
						cursor_x_node.setStyle('top', mouse_y+'px');
						cursor_y_node.setStyle('left', mouse_x+'px');
						
						// show cursors
						cursor_x_node.set('class', _this.show_class);
						cursor_y_node.set('class', _this.show_class);
					}
					else
					{
						cursor_x_node.set('class', _this.hide_class);
						cursor_y_node.set('class', _this.hide_class);
					}
				}
			});
		}
	},
	
	/**
	 * freeze cursor
	 * @param	object	handler_node
	 * @return	void
	 */
	freezeCursor: function(handler_node)
	{
		var content_node	= $(this.content_id);
		var cursor_x_node	= $(this.cursor_x_id);
		var cursor_y_node	= $(this.cursor_y_id);
		
		// get coordinates handler
		if (handler_node && content_node && cursor_x_node && cursor_y_node)
		{
			var handler_coords		= handler_node.getCoordinates();
			var handler_height		= (handler_coords.height).toInt();
			var handler_width		= (handler_coords.width).toInt();
			var handler_left		= (handler_coords.left).toInt();
			var handler_top			= (handler_coords.top).toInt();
			
			var content_coords		= content_node.getCoordinates();
			var content_left		= (content_coords.left).toInt();
			var content_top			= (content_coords.top).toInt();
			
			var handler_top_adjust	= Math.ceil((handler_height / 2)).toInt();
			var handler_left_adjust	= Math.ceil((handler_width / 2)).toInt();
			handler_top				= handler_top + handler_top_adjust - 1;
			handler_left			= handler_left + handler_left_adjust - 1;
			
			var freeze_left			= (handler_left - content_left).toInt();
			var freeze_top			= (handler_top - content_top).toInt();
			
			// set new position
			cursor_x_node.setStyle('top', freeze_top+'px');
			cursor_y_node.setStyle('left', freeze_left+'px');
		}
	},
	
	/**
	 * set hover events
	 * @return	void
	 */
	setHoverEvents: function()
	{
		var _this				= this;
		var content_month_node	= $(this.content_month_id);
		var content_node		= $(this.content_id);
		
		if (content_month_node && content_node)
		{
			var td_nodes		= content_month_node.getElements('td');
			var total_td_nodes	= td_nodes.length;
			
			if (total_td_nodes > 0)
			{
				td_nodes.each(function(td_node)
				{
					var filters_node = td_node.getElement('.'+_this.filters_class);
					
					if (filters_node)
					{
						var empty_filter_node = filters_node.getElement('.'+_this.filter_empty_class);
						
						if (!empty_filter_node)
						{
							filters_node.removeEvents();
							
							filters_node.addEvents(
							{
								'click' : function()
								{
									// remove cursor events
									content_node.removeEvents();
									
									// freeze cursor
									_this.freezeCursor(this);
									
									// load event popup
									_this.loadEventPopup(this);
									
									return false;
								}
							});
						}
					}
					
					td_node.removeEvents();
					
					td_node.addEvents(
					{
						'mouseenter' : function()
						{
							_this.cellHover(this, _this.active_class);
						},
						
						'mouseleave' : function()
						{
							_this.cellHover(this, '');
						}
					});
				});
			}
		}
	},
	
	/**
	 * set scroll events
	 * @return	void
	 */
	setScrollEvents: function()
	{
		// set vars
		var _this						= this;
		var content_node				= $(this.content_id);
		var content_month_node			= $(this.content_month_id);
		var content_day_node			= $(this.content_day_id);
		
		if (content_day_node) content_month_node = content_day_node;
		
		var content_coordinates			= content_node.getCoordinates();
		var content_width				= content_coordinates.width.toInt();
		var content_month_coordinates	= content_month_node.getCoordinates();
		var content_month_width			= content_month_coordinates.width.toInt();
		
		var button_previous_node		= $(this.button_previous_id);
		var button_next_node			= $(this.button_next_id);
		
		if (content_month_node)
		{
			if (button_previous_node)
			{
				button_previous_node.removeEvents();
				
				button_previous_node.addEvent('click', function()
				{
					var content_month_left = content_month_node.getStyle('left').toInt();
					
					// check if allowed to scroll
					if (content_month_left < 0)
					{
						// show blocker
						_this.blocker_node.set('class', _this.show_class);
						
						// calculate new left position
						var content_month_left_new = content_month_left <= (0 - content_width) ? content_month_left + content_width : 0;
						
						// start effect
						var slider_effect = new Fx.Morph(content_month_node, {duration: _this.slider_duration, transition: Fx.Transitions.Quad.easeOut});
				 		
						slider_effect.start(
						{
							'left': [content_month_left, content_month_left_new]
						}).chain(function()
						{
							// hide blocker
							_this.blocker_node.set('class', _this.hide_class);
							
							// toggle times
							if ($(_this.time_left_id)) $(_this.time_left_id).set('class', _this.visible_class);
							if ($(_this.time_first_id)) $(_this.time_first_id).set('class', _this.hidden_class);
						});
					}
					
					return false;
				});
			}
			
			if (button_next_node)
			{
				button_next_node.removeEvents();
				
				button_next_node.addEvent('click', function()
				{
					// check if allowed to scroll
					var content_month_left = content_month_node.getStyle('left').toInt();
					
					// check if allowed to scroll
					if (content_month_left > (0 - (content_month_width - content_width)))
					{
						// show blocker
						_this.blocker_node.set('class', _this.show_class);
						
						// calculate new left position
						var content_month_left_new = (content_month_width + content_month_left) > (content_width * 2) ? content_month_left - content_width : content_month_left - ((content_month_width + content_month_left) - content_width);
						
						// toggle times
						if ($(_this.time_left_id)) $(_this.time_left_id).set('class', _this.hidden_class);
						if ($(_this.time_first_id)) $(_this.time_first_id).set('class', _this.visible_class);
						
						// start effect
						var slider_effect = new Fx.Morph(content_month_node, {duration: _this.slider_duration, transition: Fx.Transitions.Quad.easeOut});
				 		
						slider_effect.start(
						{
							'left': [content_month_left, content_month_left_new]
						}).chain(function()
						{
							// hide blocker
							_this.blocker_node.set('class', _this.hide_class);
						});
					}
					
					return false;
				});
			}
		}
	},
	
	/**
	 * set view switch events
	 * @return	void
	 */
	setViewSwitchEvents: function()
	{
		var _this				= this;
		var view_switch_node	= $(this.view_switch_id);
		
		if (view_switch_node)
		{
			view_switch_anchor_node	= view_switch_node.getElement('a');
			
			if (view_switch_anchor_node)
			{
				view_switch_anchor_node.removeEvents();
				
				view_switch_anchor_node.addEvent('click', function()
				{
					// load month content
					_this.loadMonthContent();
					
					return false;
				});
			}
		}
	},
	
	/**
	 * set day content events
	 * @return	void
	 */
	setDayContentEvents: function()
	{
		// scroll events
		this.setScrollEvents();
		
		// day filter events
		this.setDayFilterEvents();		
		
		// day navigate events
		this.setDayNavigateEvents();
		
		// day zoom events
		this.setDayZoomEvents();
	},
	
	/**
	 * filter
	 * @param	object checkbox_node
	 * @param	string display_type
	 * @return void
	 */
	filter: function(checkbox_node, display_type)
	{
		if (checkbox_node)
		{
			// get checkbox id
			var checkbox_id	= checkbox_node.get('id');
			
			if (checkbox_id)
			{
				var filter_label_nodes			= this.root_node.getElements('.'+checkbox_id);
				var total_filter_label_nodes	= filter_label_nodes.length;
				
				if (total_filter_label_nodes > 0)
				{
					filter_label_nodes.each(function(filter_label_node)
					{
						filter_label_node.setStyle('display', display_type);
					});
				}
			}
		}
	},
	
	/**
	 * filter day content
	 * @param	object checkbox_node
	 * @param	string display_type
	 * @return void
	 */
	filterDayContent: function(checkbox_node, display_type)
	{
		if (checkbox_node)
		{
			// get checkbox id
			var checkbox_id	= checkbox_node.get('id');
			
			if (checkbox_id)
			{
				var checkbox_type				= checkbox_id.replace(this.filter_prefix, '');
				var filter_label_nodes			= this.root_node.getElements('.'+this.content_day_event_prefix+checkbox_type);
				var total_filter_label_nodes	= filter_label_nodes.length;
				
				if (total_filter_label_nodes > 0)
				{
					filter_label_nodes.each(function(filter_label_node)
					{
						filter_label_node.setStyle('display', display_type);
					});
				}
			}
		}
	},
	
	/**
	 * cell hover
	 * @param	object cell_node
	 * @param	string cell_anchor_class
	 * @return	void
	 */
	cellHover: function(cell_node, cell_anchor_class)
	{
		if (cell_node)
		{
			// get cell index
			var cell_class		= cell_node.get('class');
			var cell_class_new	= cell_class.replace(this.cell_prefix, '');
			var arr_index		= cell_class_new.split('_');
			var row_index		= arr_index[0].toInt();
			var cell_index		= arr_index[1].toInt();
			
			if (row_index > 0)
			{
				var content_events_node	= $(this.content_events_id);
				
				if (content_events_node)
				{
					var row_nodes		= content_events_node.getElements('.'+this.content_event_class);
					var total_row_nodes	= row_nodes.length;
					
					if (total_row_nodes > 0)
					{
						for (var i=1; i<=total_row_nodes; i++)
						{
							var row_node = row_nodes[i-1];
							
							if (row_node)
							{
								row_node.setStyle('color', '');
								
								if (i == row_index && cell_anchor_class) row_node.setStyle('color', '#FFF');
							}
						}
					}
				}
			}
			
			// get row index
			if (cell_index > 0)
			{
				var content_month_node	= $(this.content_month_id);
				
				if (content_month_node)
				{
					var cell_nodes			= content_month_node.getElements('th.'+this.cell_prefix + cell_index);
					var total_cell_nodes	= cell_nodes.length;
					
					if (total_cell_nodes > 0)
					{
						cell_nodes.each(function(cell_node)
						{
							var cell_anchor_node = cell_node.getElement('a');
							
							if (cell_anchor_node) cell_anchor_node.set('class', cell_anchor_class);
						});
					}
				}
			}
		}
	},
	
	/**
	 * load event popup
	 * @param	object	handler_node
	 * @return	void
	 */
	loadEventPopup: function(handler_node)
	{
		if (handler_node)
		{
			// set vars
			var _this	= this;
			
			// set params
			var arr_id		= handler_node.id.split('_');
			var location_id	= arr_id[1].toInt();
			var date_day	= arr_id[2].toInt();
			
			// loader
			var http_request = new Request({
				url:		this.location_url,
				method:		'get',
				data:		'location_id='+location_id+'&date_day='+date_day,
				onRequest:	function()
				{
					// show blocker
					_this.blocker_node.set('class', _this.show_class);
					
					// create loader
					_this.createEventPopupLoader(handler_node);
				},
				onSuccess:	function(popup_content)
				{
					// hide blocker
					_this.blocker_node.set('class', _this.hide_class);
					
					// remove loader
					_this.removeEventPopupLoader();
					
					// create popup
					_this.createEventPopup(handler_node, popup_content);
				}
			});
			
			http_request.send();
		}
	},
	
	/**
	 * create event popup
	 * @param	object	handler_node
	 * @param	html	popup_content
	 * @return	void
	 */
	createEventPopup: function(handler_node, popup_content)
	{
		var _this = this;
		
		if (!$(this.event_popup_id) && handler_node && popup_content)
		{
			// create nodes
			var popup = new Element('div', 
			{
				'id' 	: this.event_popup_id,
				'class'	: this.hidden_class,
				'html'	: popup_content
			});
			
			var popup_close = new Element('a', 
			{
				'href'	: '#',
				'id' 	: this.event_popup_close_id
			});
			
			// inject nodes
			popup.inject(this.document_node);
			popup_close.inject(popup);
			
			// set events
			popup_close.removeEvents();
			
			popup_close.addEvents(
			{
				'click' : function()
				{
					_this.removeEventPopup();
					
					return false;
				}
			});
			
			// show blocker
			this.blocker_node.set('class', this.show_class);
			
			// set blocker event
			this.blocker_node.removeEvents();
			
			this.blocker_node.addEvents(
			{
				'click' : function()
				{
					_this.removeEventPopup();
					
					return false;
				}
			});
			
			// position popup
			this.positionEventPopup(handler_node);
		}
	},
	
	/**
	 * position event popup
	 * @return	void
	 */
	positionEventPopup: function(handler_node)
	{
		var content_node	= $(this.content_id);
		var popup_node		= $(this.event_popup_id);
		var popup_img_node	= $(this.event_popup_img_id);
		var popup_txt_node	= $(this.event_popup_txt_id);
		
		if (handler_node && content_node && popup_node)
		{
			// grid position
			var content_coordinates	= content_node.getCoordinates();
			var content_width		= (content_coordinates.width).toInt();
			var content_height		= (content_coordinates.height - this.month_header_height).toInt();
			var content_top_start	= (content_coordinates.top + this.month_header_height).toInt();
			var content_top_end		= (content_top_start + content_height).toInt();
			var content_left_start	= (content_coordinates.left).toInt();
			var content_left_end	= (content_left_start + content_width).toInt();
			
			// popup image position
			var popup_img_coords	= popup_img_node.getCoordinates();
			var popup_img_width		= popup_img_coords.width.toInt();
			var popup_img_height	= popup_img_coords.height.toInt();
			
			// popup text position
			var popup_txt_coords	= popup_txt_node.getCoordinates();
			var popup_txt_width		= popup_txt_coords.width.toInt();
			var popup_txt_height	= popup_txt_coords.height.toInt();
			
			// popup info
			var popup_height		= popup_txt_height > popup_img_height ? popup_txt_height : popup_img_height;
			
			popup_node.setStyles({
				'height' : popup_height+'px'
			});
			
			// handler position
			var handler_coords			= handler_node.getCoordinates();
			var handler_width			= (handler_coords.width).toInt();
			var handler_height			= (handler_coords.height).toInt();
			var handler_left_original	= (handler_coords.left).toInt();
			
			var handler_left_adjust		= Math.ceil((handler_width / 2)).toInt();
			var handler_top_original	= (handler_coords.top).toInt();
			var handler_top_adjust		= Math.ceil((handler_height / 2)).toInt();
			var handler_top				= handler_top_original + handler_top_adjust - 1;
			var handler_left			= (handler_left_original - popup_img_width) + handler_left_adjust - 1;
			
			//*******************
			// set top position *
			//*******************
			var popup_top_end	= (handler_top + popup_height).toInt();
			
			// above cursor line
			if (popup_top_end > content_top_end)
			{
				popup_node.setStyles({
					'top' : ((handler_top - popup_height) + 2)+'px'
				});
				
				popup_img_node.setStyles({
					'bottom' : 0
				});
				
				popup_txt_node.setStyles({
					'bottom' : 0
				});
			}
			
			// under cursor line
			else
			{
				popup_node.setStyles({
					'top' : (handler_top)+'px'
				});
				
				popup_img_node.setStyles({
					'top' : 0
				});
				
				popup_txt_node.setStyles({
					'top' : 0
				});
			}
			
			//********************
			// set left position *
			//********************
			var popup_left_start	= (handler_left).toInt();
			var popup_left_end		= (handler_left_original + popup_txt_width).toInt();
			
			// on the left side of the cursor line
			if (popup_left_end > content_left_end)
			{
				popup_node.setStyles({
					'left' : ((handler_left - popup_txt_width) + 2) +'px'
				});
				
				popup_img_node.setStyles({
					'left' : 0
				});
				
				popup_txt_node.setStyles({
					'right' : 0
				});
			}
			
			else if (popup_left_start < content_left_start)
			{
				popup_node.setStyles({
					'left' : (handler_left_original + handler_left_adjust - 1) +'px'
				});
				
				popup_img_node.setStyles({
					'left' : 0
				});
				
				popup_txt_node.setStyles({
					'right' : 0
				});
			}
			
			// on the right side of the cursor line
			else
			{
				popup_node.setStyles({
					'left' : (handler_left)+'px'
				});
				
				popup_img_node.setStyles({
					'left' : 0
				});
				
				popup_txt_node.setStyles({
					'right' : 0
				});
			}
			
			// show popup
			popup_node.set('class', this.visible_class);
		}
	},
	
	/**
	 * remove event popup
	 * @return	void
	 */
	removeEventPopup: function()
	{
		var _this			= this;
		var popup			= $(this.event_popup_id);
		var blocker_node	= $(this.blocker_id);
		var cursor_x_node	= $(this.cursor_x_id);
		var cursor_y_node	= $(this.cursor_y_id);
		
		if (popup && blocker_node && cursor_x_node && cursor_y_node)
		{
			// remove popup
			popup.dispose();
			
			// hide cursor
			cursor_x_node.set('class', _this.hide_class);
			cursor_y_node.set('class', _this.hide_class);
			
			// set cursor events
			_this.setCursorEvents();
			
			// hide blocker
			blocker_node.set('class', _this.hide_class);
		}
	},
	
	/**
	 * create month content
	 * @param	string	month_content
	 * @return	void
	 */
	createMonthContent: function(month_content)
	{
		if (month_content)
		{
			// set html
			this.root_node.set('html', month_content);
			
			// set dimensions of content node
			this.setContentDimensions();
					
			// set events
			this.setEvents();
		}
	},
	
	/**
	 * create day content
	 * @param	string	day_content
	 * @return	void
	 */
	createDayContent: function(day_content)
	{
		if (day_content)
		{
			// set html
			this.root_node.set('html', day_content);
			
			// set content dimensions
			this.setContentDimensions();
			
			// set day content events
			this.setDayContentEvents();
			
			// set view switch events
			this.setViewSwitchEvents();
		}
	},
	
	/**
	 * create event popup loader
	 * @param	object	handler_node
	 * @return	void
	 */
	createEventPopupLoader: function(handler_node)
	{
		if (handler_node)
		{
			// get coordinates handler
			var handler_coords		= handler_node.getCoordinates();
			var handler_left		= (handler_coords.left).toInt();
			var handler_top			= (handler_coords.top).toInt();
			
			var popup_loader = new Element('img', 
			{
				'id' 		: this.event_popup_loader_id,
				'src'		: this.loader_url,
				'styles'	: 
				{
					'left'	: handler_left+'px',
					'top'	: handler_top+'px'
				}
			});
			
			// inject nodes
			popup_loader.inject(this.document_node);
		}
	},
	
	/**
	 * remove event popup loader
	 * @return	void
	 */
	removeEventPopupLoader: function()
	{
		if ($(this.event_popup_loader_id)) $(this.event_popup_loader_id).dispose();
	},
	
	/**
	 * create content loader
	 * @param	object	handler_node
	 * @return	void
	 */
	createContentLoader: function()
	{
		// get coordinates handler
		var content_loader = new Element('img', 
		{
			'id' 		: this.content_loader_id,
			'src'		: this.loader_url,
			'styles'	: 
			{
				'right'	: '10px',
				'top'	:'10px'
			}
		});
		
		// inject nodes
		content_loader.inject(this.root_node);
	},
	
	/**
	 * remove content loader
	 * @return	void
	 */
	removeContentLoader: function()
	{
		if ($(this.content_loader_id)) $(this.content_loader_id).dispose();
	},
	
	/**
	 * set event type sessions
	 * @return	void
	 */
	setEventTypeSessions: function()
	{
		// get checked boxes
		var checked_filter_see	= $('calendar_filter_see').get('class') == this.in_active_class ? 1 : 2;
		var checked_filter_do	= $('calendar_filter_do').get('class') == this.in_active_class ? 1 : 2;
		var checked_filter_exp	= $('calendar_filter_exp').get('class') == this.in_active_class ? 1 : 2;
		
		var obj_params = new Hash(
		{
			'event_type_see'	: checked_filter_see,
			'event_type_do'		: checked_filter_do,
			'event_type_exp'	: checked_filter_exp
		});
		
		// loader
		var http_request = new Request({
			url:		this.event_type_session_url,
			method:		'get',
			data:		obj_params
		});
		
		http_request.send();
	}
	
});