(
	function ($) 
	{
		var methods = 
		{
			init : function(options) 
			{	
				// ensure correct visibility
				this.children('ul').each(function() {
						$(this).find('ul').each(function() {
							$(this).css('display', 'none');
						});	
				});	
				
				element = this;
				this.find('a').each(function()
					{
						$(this).click (
							function()
							{
								if (element.hasClass('__fn_simpleAccordion_Blocked'))
								{
									return;
								}	
								$.fn.simpleAccordion('expand', this, false);
								if (options && options.callback)
								{
									options.callback.apply(this);
								}
							}
						);
					}
				);
			}
			,
			
			isLocked : function()
			{
				return this.hasClass('__fn_simpleAccordion_Blocked');			
			}
			
			,			
			
			lock : function()
			{
				if (!this.simpleAccordion('isLocked'))
				{
					this.addClass('__fn_simpleAccordion_Blocked');
				}
			}

			,

			unlock : function()
			{
				if (this.simpleAccordion('isLocked'))
				{
					this.removeClass('__fn_simpleAccordion_Blocked');
				}
			}

			,

			expand : function (element, invokeAction)
			{
				// retain object reference
				var _element = $(element);
				var _this = _element.closest('div');

				// check locking
				if (_this.simpleAccordion('isLocked'))
				{
					return;	
				}
				
				// remove all selected markers and mark this element
				_this.find('.selected').each(function() {
					$(this).removeClass('selected');	
				});
				_current = _element;
				while (true)
				{
					_current.parent().addClass('selected');

					if(_this[0] == _current.parent().parent().parent()[0])
					{
						break;
					}	
					
					_current = _current.parent().parent().parent().children('a');
				}				
				
				// close all
				_this.children('ul').each(function() {
					$(this).find('ul').each(function() {
						$(this).css('display', 'none');
					});	
				});
				
				// expand to this point
				_current = _element;
				while (true)
				{
					_current.siblings('ul').each(function() {
						$(this).css('display', 'block');
					});
					
					if(_this[0] == _current.parent().parent().parent()[0])
					{
						break;
					}	
					
					_current = _current.parent().parent().parent().children('a');
				}
				
				
				// clean siblings
				_current = _element;
				while (true)
				{
					if(_current.parent().parent().parent().children('a').parent().parent().parent()[0] != _this[0]) 
					{
						_current.parent().parent().parent().siblings('li').each(function() {
							$(this).css('display', 'none');
						});
					}
					
					if(_this[0] == _current.parent().parent().parent()[0])
					{
						break;
					}	
					
					_current = _current.parent().parent().parent().children('a');
				}
				
				// close visible siblings if not top menu and not leaf
				if (_element.parent().parent().parent()[0] != _this[0])
				{
					if (_element.next('ul').length != 0)
					{	
						_element.parent().siblings('li').each(function() {
							$(this).css('display', 'none');
						});
					}
				}
				
				// display sibling links
				_element.siblings('ul').each(function() {
					$(this).children('li').each(function() {
						$(this).css('display', 'block');
					});
				});	

				// fade in content
				var nextElement = _element.next('ul');
				if (nextElement.length == 0)
				{
					nextElement = _element.parent().parent();
				}	
				
				nextElement.addClass('separator');

				if (invokeAction)
				{
					if(_element.attr('onclick'))
						{
							_element.attr('onclick').apply(_element[0]);
						};
				}
			},
			
			getSelectedPath : function()
			{
				selectedList =  this.find('.selected');
				selectedElements = [];
				for (i =0; i < selectedList.length; i++)
				{
					selectedElements[i] = $($(selectedList[i]).children('a')[0]);
				}
				
				return selectedElements;
			}
		};
	
		$.fn.simpleAccordion = function( method ) {
		    if ( methods[method] ) 
		    {
		    	return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		    } 
		    else if (typeof method === 'object' || ! method ) 
		    {
		    	return methods.init.apply( this, arguments );
		    } 
		    else 
		    {
		    	throw new Exception( 'Method ' +  method + ' does not exist on jQuery.simpleAccordion' );
		    }    
		};
	}
)(jQuery);
