var ActiveLink = new Class({
	container: '',

	initialize: function(container){
		if(!container){
			this.container = $$('body')[0];
		} else { 
			this.container = container;
		}

		return this.findActiveLink(this.getLinks(this.container), this.getUrl());
	},

	getUrl: function(){
		return window.location.href;
	},

	getLinks: function(container){
		return container.getElements('a');
	},

	parseUrl: function(url){
		PHP = new PHP_JS();
		var out = PHP.parse_url(url);

		if(out['path']){
			out['path'] = out['path'].replace(new RegExp(/\/$/), '');
		}

		return out;
	},

	findActiveLink: function(links, current){
		current = this.parseUrl(current);

		var self = this;
		var out = [];
		links.each(function(el){
			var link = self.parseUrl(el.get('href'));
			if((current['host'] == link['host']) || !(link['host']) || (link['host'] == '')){
				if(current['path'] == link['path']){
					out.push(el);
				}
			} 
		});

		return out;
	}
});

var ExpandingMenu = new Class({
	menu: '',
	submenus: [],

	activelinks: [],

	startmenu: false,
	activemenu: false,

	timer: false,

	initialize: function(menu){
		if(!menu){
			return false;
		} else {
			this.menu = menu;
		}

		// load submenu headers
		this.submenus = this.getSubmenus();

		// add event listeners to items with submenus
		var self = this;
		this.submenus.each(function(item){
			// Expands menus when they have mouseenter.				
			item.parent.addEvent('mouseenter', function(){
				// collapse the start menu (temorarily) if any other item is selected.
				if((self.startmenu) && (self.activemenu == self.startmenu) && (item != self.startmenu)){ 
					self.unsetActive(self.startmenu);
				// collapse menu currently active.
				} else if((self.activemenu) && (self.activemenu != item)){
					self.unsetActive(self.activemenu);
				}

				// if the item is already active, do not activate it! 
				if(item != self.activemenu){ 
					self.setActive(item);
				}

				if(self.timer){ clearTimeout(self.timer); }
			});

			// Restores the start menu if it has been collapsed.
			item.parent.addEvent('mouseleave', function(){
				if(self.timer){ clearTimeout(self.timer); }

				// The collapsing of a menu can cause an inadvertant mouseleave event (because the target menu may move vertically). 
				// In order to avoid this, we delay the automatic collapse/restore by 2 seconds.
				// As it is possible for multiple collapse/restores to get queued up, only one timer can run at a time.
				self.timer = setTimeout(function(){
					// startmenu should only be (temporarily) collapsed when a different menu is selected. 
					if(self.startmenu != self.activemenu){ 
						self.unsetActive(item);
					}

					// whenever we hide a menu, re-activate the startmenu (displayed by default). only time to behave differently is when EXPLICITLY told to collapse it.
			 		if((self.startmenu) && (item != self.startmenu)){ 
						self.setActive(self.startmenu); 
					} 
				}, 2000);
			});
		});

		// grabs active links and opens any submenus
		this.setStartState();
	},

	getSubmenus: function(){
		var submenus = this.menu.getChildren('li');
		var out = [];

		submenus.each(function(el){
			if(el.getChildren('ul').length > 0){
				var submenu = el.getChildren('ul')[0];
				var dimensions = submenu.measure(function(){
					return this.getSize();
				});

				out.push({ 
					parent: el, // top level menu item
					menu: submenu, // the nested items
					x: dimensions.x, // the display width of the nested items
					y: dimensions.y, // the display height of the nested items
					fx: new Fx.Tween(submenu, { // the mootools effect object instance (per submenu)
							duration: 500, 
							link: 'cancel',
							onComplete: function(){
								if(submenu.getHeight() <= 0){ // if height is 0, we are hiding the item.
									submenu.setStyles({ display: 'none' });
								}
							}
					})
				});
			}
		});

		return out;
	},

	setStartState: function(){
		var self = this;

		this.activelinks = new ActiveLink(this.menu);
		this.activelinks.each(function(el){
			el.addClass('active'); // we do this here because setActive only holds for hover action.

			var op = 'parent';
			var item = el.getParent('li');
			if(item.getParent('ul') != self.menu){ // TODO: there should be a better way of assessing this in case root menu is not a ul.
				op = 'menu';
				item = item.getParent('ul');
			}
				
			self.submenus.each(function(submenu){
				if(submenu[op] == item){
					self.startmenu = submenu; // preserves start state (so that we might fall back to this item).
					self.setActive(submenu, true); // sets submenu to 'open'.
				}
			});
		});
	},

	setActive: function(params, instant){
		this.activemenu = params;

		params.menu.setStyles({ height: '0px', overflow: 'hidden', display: 'block' });
		if(instant){ // skip animation and make the change instantly.
			params.menu.setStyle('height', params.y);
		} else {
			params.fx.start('height', params.y);
		}

		params.parent.addClass('expanded'); // class is not for logic, provides styling class for any external CSS rules.
	},

	unsetActive: function(params, instant){
		this.activemenu = false;

		if(instant){ // skip animation and make the change instantly.
			params.menu.setStyle('height', 0);
		} else {
			params.fx.start('height', 0);
		}
		
		params.parent.removeClass('expanded');
	}
});

