var currentMenu = null;

var Menu = Class.create(
{
	initialize: function(element, options)
	{
		this.root = $(element);
		
		this.active = false;
		
		this.options = {
			orientation:     	'vertical',
			handle:				null,
			trigger:			'hover',
			delay:				350
		};

		Object.extend(this.options, options || { });
		
		// ---------
		
		var zIndex = this.root.getStyle("zIndex");
		
		if(!zIndex)
		{
			zIndex = 100;
		}
		
		// ---------
		
		var menus = this.root.select('.menu');
		
		for(var i = 0; i < menus.length; i++)
		{
			menus[i].depth = this.getDepth(menus[i]);
			
			menus[i].parentMenu = menus[i].up('.menu');

			menus[i].setStyle({zIndex: (zIndex + menus[i].depth), display: 'none'});
			
			menus[i].addClassName('level' + menus[i].depth);
		}
		
		// ----------
		
		var menuItems = this.root.select('.menuitem');
		
		for(var i = 0; i < menuItems.length; i++)
		{
			menuItems[i].observe('mouseover',	this.mouseOver.bindAsEventListener(this));
		}
		
		// --------
		
		this.handle = $(this.options.handle);

		if(this.handle)
		{
			if(this.options.trigger == "hover")
			{
				this.handle.observe('mouseover', this.activate.bindAsEventListener(this));
				this.handle.observe('mouseout', this.deactivate.bindAsEventListener(this));
			}
			else
			{
				this.handle.observe('mousedown', this.start.bindAsEventListener(this));
			}
		}
		else
		{
			var topItems = this.root.select('.top');
			for(var i = 0; i < topItems.length; i++)
			{
				topItems[i].observe('mouseover', this.activate.bindAsEventListener(this));
				topItems[i].observe('mouseout', this.deactivate.bindAsEventListener(this));
			}
		}
	},
	
	start: function(inEvent)
	{
		if(inEvent)
		{
			try
			{
				Event.stop(inEvent);
			}
			catch (e)
			{
				
			}
		}
		
		if(currentMenu)
		{
			currentMenu.done();
		}
		
		currentMenu = this;
		
		// ---------
	
		this.active = true;
	
		this.doneFunction = this.done.bindAsEventListener(this);

		document.observe('mousedown', this.doneFunction);
		
		this.showMenu(this.root);
	},
	
	done: function(inEvent)
	{
		if(inEvent != null)
		{
			var element = inEvent.srcElement ? inEvent.srcElement : inEvent.target;
			
			if(element.tagName != "A")
			{
				this.hideMenus(this.root);
			}
		}
		
		this.active = false;
		
		document.stopObserving('mousedown', this.doneFunction);
	},

	activate: function(event)
	{
		if(!this.active)
		{
			if(this.options.delay <= 0)
			{
				this.start();
			}
			else
			{
				this.activateTimer = setTimeout(this.start.bind(this), this.options.delay);
			}
		}
	},
	
	deactivate: function(event)
	{
		if(this.activateTimer)
		{
			clearTimeout(this.activateTimer);
			
			this.activateTimer = null;
		}
	},
	
	mouseOver: function(event)
	{
		if(!this.active)
		{
			return;
		}
		
		var element = event.element();
		
		if(!element.hasClassName('menuitem'))
		{
			element = element.up('.menuitem');
		}
		
		if(!element)
		{
			return;
		}

		this.showMenu(element);
	},
	
	showMenu: function(element)
	{
		var menu = element.down('.menu');
		
		var parentMenu = element.up('.menu');
			
		if(parentMenu == null)
		{
			parentMenu = element.up('.sitenavigation');
		}
		
		this.hideMenus(parentMenu);

		if(menu && menu.getStyle("display") == "none")
		{
			menu.setStyle({display:'block', visibility:'hidden'});
			menu.forceLeft = false;
			
			var firstBounds = new Bounds(menu.select('.menuitem').first());
			var viewportBounds = new Bounds(document.viewport);
			var menuBounds = new Bounds(menu);
	
			viewportBounds.shrink(10);
			
			var yOffset = menuBounds.top - firstBounds.top - (parseInt(menu.getStyle("borderTopWidth")) || 0);

			if(menu.depth == 1)
			{
				var handleBounds = new Bounds(this.handle);
				
				if(this.options.orientation == "horizontal")
				{
					menuBounds.moveRelative("top left", handleBounds, "bottom left", -2, -yOffset);
					
					var adjustment = menuBounds.moveWithin(viewportBounds);
				
					if(adjustment.x < 0)
					{
						menuBounds.moveRelative("bottom left", handleBounds, "top left", 2, yOffset);
						
						menu.forceLeft = true;
					}
				}
				else
				{
					menuBounds.moveRelative("top left", handleBounds, "top right", 0, 2);
				}
			}
			else
			{
				var elementBounds = new Bounds(element);

				menuBounds.moveRelative("top left", elementBounds, "top right", -2, yOffset);
				
				var adjustment = menuBounds.moveWithin(viewportBounds);
				
				if(adjustment.x < 0 || (parentMenu && parentMenu.forceLeft))
				{
					menuBounds.moveRelative("top right", elementBounds, "top left", 2, -yOffset);
					
					adjustment = menuBounds.moveWithin(viewportBounds);
					
					if(adjustment.x > 0)
					{
						menuBounds.moveRelative("top left", elementBounds, "top right", -2, yOffset);
					}
					else
					{
						menu.forceLeft = true;
					}
				}
			}
			
			var adjustment = menuBounds.moveWithin(viewportBounds);
			
			if(adjustment.y < 0)
			{
				menuBounds.moveBy(0, adjustment.y);
			}
			
			menuBounds.syncElement();
			
			menu.setStyle({visibility:'visible'});
			
			// -------
		
			var ancestors = menu.ancestors();
			
			for(var i = 0; i < ancestors.length; i++)
			{
				if(ancestors[i] == this.root)
				{
					break;
				}
			
				if(ancestors[i].hasClassName('menuitem'))
				{
					ancestors[i].addClassName('hilite');
				}
			}
		}
	},
	
	hideMenus: function(element)
	{
		if(element)
		{
			var menus = element.select('.menu');
			
			for(var i = 0; i < menus.length; i++)
			{
				menus[i].style.display = 'none';
			}

			var menuItems = element.select('.menuitem');
			
			for(var i = 0; i < menuItems.length; i++)
			{
				menuItems[i].removeClassName('hilite');
			}
		}
	},
	
	getDepth: function(element)
	{
		var depth = element.hasClassName("menu") ? 0 : -1;
		
		while(element && element != this.root)
		{
			element = element.up('.menu');
		
			depth++;
		}
	
		return depth;
	}
});


