var ns = {};
ns.userElements = {};
ns.userElements.jLogoMenu = function (obj_options)
{
	var jbj_menu = null;
	var jbj_logo = null;
	
	var _construct = function (obj_options)
	{
		// Check parameters
		if (undefined === obj_options.menu_id) 		{ console.warn('Could not create a new LogoMenu without an id!'); return null; }
		if (undefined === obj_options.logo_id) {
			obj_options.logo_id = obj_options.menu_id.replace('_menu', '_logo');
		}
		
		// Get elements
		var obj_menu = document.getElementById(obj_options.menu_id);
		if (!obj_menu) 								{ console.warn('Could not find the element with id "' + obj_options.menu_id + '"!'); return null; }
		if (obj_menu)
		{
			jbj_menu = $(obj_menu);
		}
		
		var obj_logo = document.getElementById(obj_options.logo_id);
		if (!obj_logo) { obj_logo = _createLogo(obj_options.logo_id); }
		if (obj_logo)
		{
			jbj_logo = $(obj_logo);
		}
		
		// Return
		return;
	}
	
	var _createLogo = function (str_logo_id)
	{
		// Check parameters
		if (!jbj_menu) 								{ console.warn('Could not find the menu!'); return null; }
		
		// Create logo
		if (jbj_menu)
		{
			jbj_logo = jbj_menu.clone();
			jbj_logo
				.attr('id', str_logo_id)
				.find(':not(.logo)').remove().end();
			jbj_logo
				.appendTo(jbj_menu.parent());
		}
		
		// Return
		return;
	}
	
	var _getLogoId = function ()
	{
		// Check parameters
		if (!jbj_logo) 								{ console.warn('Could not find the logo!'); return null; }
		
		// Get logo id
		return jbj_logo.attr('id');
	}
	
	var _getMenuId = function ()
	{
		// Check parameters
		if (!jbj_menu) 								{ console.warn('Could not find the menu!'); return null; }
		
		// Get logo id
		return jbj_menu.attr('id');
	}
	
	var _initMenu = function ()
	{
		// Check parameters
		if (!jbj_menu) 								{ console.warn('Could not find the menu!'); return null; }
		
		// Initiate menu
		if (jbj_menu && jbj_logo)
		{
			jbj_logo.show();
			jbj_menu.hide();
		}
		
		// Return
		return;
	}
	
	var _showMenu = function (event)
	{
		// Check exceptions
		if (0 !== $(document).find('.ui-draggable-dragging').length) { return false; }
		
		// Show menu
		if (jbj_menu && jbj_logo)
		{
			jbj_menu.addClass('active');
			setTimeout(function () {
				if ((false === jbj_menu.is(':visible')) && (true === jbj_menu.hasClass('active')))
				{
					jbj_menu.stop(true, true).animate({ // TODO add options
					  	'height': 'show',
					  	'opacity': 'show'
					}, 'fast' );
				}
			}, 100);
		}
		
		// Return
		return true;
	}
	
	var _hideMenu = function (event)
	{
		// Check exceptions
		if (0 !== $(document).find('.ui-draggable-dragging').length) { return false; }
		
		// Show menu
		if (jbj_menu && jbj_logo)
		{
			jbj_menu.removeClass('active');
			setTimeout(function () {
				if ((true === jbj_menu.is(':visible')) && (false === jbj_menu.hasClass('active')))
				{
					jbj_menu.stop(true, true).animate({ // TODO add options
					  	'height': 'hide',
			  			'opacity': 'hide'
					}, 'fast' );
				}
			}, 100);
		}
		
		// Return
		return true;
	}
	
	_construct(obj_options);
	return {
		'getMenuId': _getMenuId,
		'getLogoId': _getLogoId,
		'initMenu': _initMenu,
		'showMenu': _showMenu,
		'hideMenu': _hideMenu
	};
}

ns.userElements.jActivatorElement = function (obj_options)
{
	var jbj_activator = null;
	var jbj_target = null;
	
	var _construct = function (obj_options)
	{
		// Check parameters
		if (undefined === obj_options.activator_id) 		{ console.warn('Could not create a new ActivatorElement without an id!'); return null; }
		if (undefined === obj_options.target_id) 			{ console.warn('Creating a new ActivatorElement is kinda pointless without a target, ain\'t it? But hey, your wish...'); }
		
		// Get elements
		var obj_activator = document.getElementById(obj_options.activator_id);
		if (!obj_activator) 								{ console.warn('Could not find the element with id "' + obj_options.activator_id + '"!'); return null; }
		if (obj_activator)
		{
			jbj_activator = $(obj_activator);
		}
		
		var obj_target = document.getElementById(obj_options.target_id);
		if (obj_target)
		{
			jbj_target = $(obj_target);
		}
		
		if (jbj_activator && jbj_target)
		{
			jbj_activator
					.bind('mouseenter', ( obj_options.activate ? obj_options.activate : _showTarget ) )
					.bind('mouseleave', ( obj_options.deactivate ? obj_options.deactivate : _hideTarget ) )
					.show();
			jbj_target
					.bind('mouseover', 	( obj_options.activate ? obj_options.activate : _showTarget ) )
					.bind('mouseout', 	( obj_options.deactivate ? obj_options.deactivate : _hideTarget ) )
					.hide();	
		}
		
		// Return
		return;
	}
	
	var _showTarget = function ()
	{
		if (jbj_target)
		{
			jbj_target.show();
		}
	}
	
	var _hideTarget = function ()
	{
		if (jbj_target)
		{
			jbj_target.hide();
		}
	}

	_construct(obj_options);
	return {
		'showTarget': _showTarget,
		'hideTarget': _hideTarget
	};
}

ns.userElements.jDesktop = function () // TODO make the desktop element a parameter
{
	var _construct = function ()
	{
		_renderWindowsOptimalHeight();
		_renderWindowsAbsolute();
		
		_resetViewportDimensions();
		_positionWindowsOnViewport();
		_addControlsToWindows();
	}
	
	
	var _getHighestZindex = function ()
	{
		var int_zindex = 0;
		$('.window').each(function ()
		{
			if ($(this).css('z-index') * 1 > int_zindex)
			{
				int_zindex = $(this).css('z-index');
			}
		});
		return int_zindex;
	}
	
	var _linkAnchorsToWindows = function (jbj_parent)
	{
		if (jbj_parent)
		{
			jbj_parent.find('a').each(function () {
				$(this).bind('click', function () {
					var jbj_window = $('#' + $(this).attr('href').replace('#', ''));
					if (jbj_window.data && jbj_window.data('events') && jbj_window.data('events').toggleWindow)
					{
						jbj_window.trigger('toggleWindow');
						return false;
					}
					console.warn('Could not find the method "toggleWindow"!');
					console.info('-> Fallback to anchor default action...');
					return true;
				});
			});
		}
	}
	
	var _renderWindowsAbsolute = function () // TODO make this a plugin
	{
		// Get initial windows positions
		var arr_window_offsets = [];
		$('.window').each(function ()
		{
			arr_window_offsets[$(this).index()] = {
				'top': $(this).offset().top + $(this).parent().scrollTop(),
				'left': $(this).offset().left + $(this).parent().scrollLeft()
			};	
		});
		
		// Position windows absolute
		$('.window').css({
			'position': 'absolute',
			'top': function () { return arr_window_offsets[$(this).index()].top; },
			'left': function () { return arr_window_offsets[$(this).index()].left }
		});
	}
	
	var _resetViewportDimensions = function ()
	{
		// Define windows viewport dimensions
		$('#windows').css({
			'margin': 0,
			'padding': 0,
			'height': '100%',
			'width': '100%'
		});
	}
	
	var _addControlsToWindows = function ()
	{
		// Enhance windows
		$('.window')
			.draggable({
				containment: '#windows',
				stack: '.window',
				distance: 0,
				scroll: true,
				handle: 'h2'
			})
			.bind({
				'initiateWindow': function ()
				{
					$(this).hide();
				},
				'showWindow': function ()
				{
					$(this).css('z-index', _getHighestZindex() + 1);
					if (false === $(this).is(':visible'))
					{
						$(this).show('fold');
					}
					return false;
				},
				'hideWindow': function ()
				{
					if (true === $(this).is(':visible'))
					{
						$(this).hide('fold');
					}
					return false;
				},
				'toggleWindow': function ()
				{
					if (false === $(this).is(':visible'))
					{
						$(this).css('z-index', _getHighestZindex() + 1);
					}
					$(this).toggle('fold');
					return false;
				}
			})
			.each(function ()
			{
				// Add close button
				var jbj_title = $(this).find('h2');
					var jbj_close = $(document.createElement('a'));
					jbj_close.attr('href', '#');
					jbj_close.attr('class', 'close');
					jbj_close.bind('click', function ()
					{
						$(this).parent().parent().trigger('hideWindow');
						return false;
					});
						var jbj_text = $(document.createTextNode('close'));
						jbj_text.appendTo(jbj_close);
					jbj_close.appendTo(jbj_title);
			})
			.trigger('initiateWindow');
	}
	
	var _renderWindowsOptimalHeight = function ()
	{
		// Redefine windows dimensions
		$('.window').each(function ()
		{
			// Get elements
			var jbj_window = $(this);
			var bln_visible = jbj_window.is(':visible');
			var jbj_title = jbj_window.find('h2');
			var jbj_content = jbj_window.find('.content');
			
			// Reset visibility
			jbj_window.show();
			
			// Reset jScrollPane
			//jbj_content.jScrollPane().data('jsp').destroy();
			
			// Get initial height
			var int_content_height_init = jbj_content.height();
			
			// Get minimal height
			jbj_content.height(0);
			
			var int_content_height_real = jbj_content[0].scrollHeight;
			jbj_content.height(int_content_height_init);
			
			// Get maximal height
			var int_window_height_max = $('#windows').innerHeight() - ( $(this).outerHeight(true) - $(this).height() );
			var int_content_height_max = int_window_height_max - jbj_title.outerHeight(true) - ( jbj_content.outerHeight(true) - jbj_content.height() );
			
			// Restrict maximal height
			int_content_height_max = 95/100 * int_content_height_max;
	
			// Set optimal height
			if (int_content_height_real < int_content_height_max)
			{
				jbj_content.height(int_content_height_real);
			}
			else
			{
				jbj_content.height(int_content_height_max);
			}
			
			// Set back visibility
			if (false === bln_visible) { jbj_window.hide(); }
			
			// Draw jScrollPane
			//jbj_content.jScrollPane();
			
		});
	};
	
	var _positionWindowsOnViewport = function ()
	{
		$('.window').each(function ()
		{
			var jbj_window = $(this);
			jbj_window.css({
				top: ($('#windows').innerHeight() - jbj_window.outerHeight(true)) / 2,
				left: (($('#windows').innerWidth() - jbj_window.outerWidth(true) - $('#navigation_menu').outerWidth()) * Math.random()) + $('#navigation_menu').outerWidth()
			});
		});
	};
	
	_construct();
	return {
		'setNavigation': _linkAnchorsToWindows
	};
}

ns.userElements.jGallery = function (obj_options) // TODO make the gallery element a parameter
{
	var jbj_window = $('#gallery_window');
	var pth_callback = null;
	var pth_images = null;
	var arr_images = null;
	
	var _construct = function (obj_options)
	{
		_activateActionAnchors();
	}
	
	var _linkAnchorsToGallery = function (jbj_anchors)
	{
		if (jbj_anchors)
		{
			jbj_anchors.find('a').each(function () {
				$(this).bind('click', function () {
					_updateGallery(
							$(this).closest('.collection_box').find('h3').html(),
							$(this).closest('.collection_box').find('.credits').html(),
							$(this).attr('href')
					);
					return false;
				});
			});
		}
	}
	
	var _activateActionAnchors = function ()
	{
		jbj_window.find('.gallery_previous').bind('click', function (event)
		{
			event.preventDefault();
			if (null === arr_images) { alert('No images found!'); }
			var pth_current = jbj_window.find('.gallery_image').attr('src');
			
			var int_next_key = 0;
			var int_last_key = 0;
			for (var str_key in arr_images)
			{
				int_last_key++;
				if (-1 !== pth_current.search(arr_images[str_key]))
				{
					int_previous_key = (str_key * 1) - 1;
					if (undefined === arr_images[int_previous_key])
					{
						int_previous_key = -1;
					}
				}
			}
			if (-1 === int_previous_key) { int_previous_key = int_last_key - 1; }
			jbj_window.find('.gallery_image').attr('src', pth_images + arr_images[int_previous_key]);
		});
		
		jbj_window.find('.gallery_next').bind('click', function (event)
		{
			event.preventDefault();
			if (null === arr_images) { alert('No images found!'); }
			var pth_current = jbj_window.find('.gallery_image').attr('src');
			
			var int_next_key = 0;
			for (var str_key in arr_images)
			{
				if (-1 !== pth_current.search(arr_images[str_key]))
				{
					int_next_key = (str_key * 1) + 1;
					if (!arr_images[int_next_key])
					{
						int_next_key = 0;
					}
				}
			}
			jbj_window.find('.gallery_image').attr('src', pth_images + arr_images[int_next_key]);
		});
	}
	
	var _setCallbackPath = function (str_path)
	{
		pth_callback = str_path;
	}
	
	var _updateGallery = function (str_title, str_credits, str_path)
	{
		arr_images = null;
		pth_images = null;
		
		jbj_window.find('.gallery_title').html(str_title);
		jbj_window.find('.gallery_credits').html(str_credits);
		jbj_window.find('.gallery_image').attr('src', '');
		
		jQuery.ajax({
			'url': pth_callback,
			'cache': false,
			'type': 'GET',
			'data': {'dir': str_path},
			'dataType': 'json',
			'async': false,
			'success': function (data)
			{
				var jbj_window = $('#gallery_window');
				if (data.error) {
					alert(data.error);
				}
				else
				{
					pth_images = str_path;
					arr_images = data;
					jbj_window.find('.gallery_image').attr('src', pth_images + arr_images['0']);
					if (jbj_window.data && jbj_window.data('events') && jbj_window.data('events').showWindow)
						{ jbj_window.trigger('showWindow'); }
				}
			}
		});
	}
	
	_construct(obj_options);
	return {
		'setNavigation': _linkAnchorsToGallery,
		'setCallback': _setCallbackPath
	};
}

