/*
Description: This provides a simple Drop Down menu with infinit levels
License: MIT-style
Authors: Arian Stolwijk
Requires: core/1.2.4: [Class.Extras,Element.Style,Element.Event]
Provides: [MooDropMenu,Element.MooDropMenu]
*/
var MooDropMenu = new Class({
		
	Implements: [Options,Events],
	
	options: {
		onOpen: function(el){
			// open the menu
			el.set('opacity',1);
		},
		onClose: function(el){
			// close the menu
			el.set('opacity',0);
		},
		onInitialize: function(el){
			// set menu to hide
			el.set('opacity',0);
		},
		withChildren: false,
		mouseoutDelay: 200,
		mouseoverDelay: 0
	},
	
	initialize: function(menu, options, level){
		this.setOptions(options);
		
		if ($type(level) == 'number') {
			this.menu = $(menu); //attach menu to object
			this.fireEvent('initialize',menu);
			
			// hook up menu's parent with event to trigger menu
			this.menu.pel.addEvents({
				
				'mouseover': function(){
					// Set the DropDownOpen status to true			
					this.menu.pel.mel.store('DropDownOpen',true);
					
					// Clear the timer of the delay
					$clear(this.timer);
					// Fire the event to open the menu
					this.timer = (function(){
						this.fireEvent('open',this.menu.pel.mel);
					}).delay(this.options.mouseoverDelay,this);		
					
				}.bind(this),
				
				'mouseout': function(){
					// Set the DropDownOpen status to false
					this.menu.pel.mel.store('DropDownOpen',false);
					
					// Clear the timer of the delay
					$clear(this.timer);
					// Build a delay before the onClose event get fired
					this.timer = (function(){
						if(!this.menu.pel.mel.retrieve('DropDownOpen')){
							this.fireEvent('close',this.menu.pel.mel);
						}
					}).delay(this.options.mouseoutDelay,this);		
					
				}.bind(this)				
			});
		}
		else {
			level = 0;
			this.menu = $(menu);
		}
		
		// grab all of the menus children - LI's in this case		
		// loop through children
		if (level == 0 || options.withChildren) {
			this.menu.getChildren('li').each(function(item, index){
				var list = item.getFirst('ul'); // Should be an A tag
				// if there is a sub menu UL
				if ($type(list) == 'element') {
					item.mel = list; // pel = parent element
					list.pel = item; // mel = menu element
					new MooDropMenu(list, options, level + 1); // hook up the subMenu
				}
			});
		}
	},
	
	toElement: function(){
		return this.menu
	}
	
});

/* So you can do like this $('nav').MooDropMenu(); or even $('nav').MooDropMenu().setStyle('border',1); */
Element.implement({
	MooDropMenu: function (options){
		this.store('MooDropMenu',new MooDropMenu(this,options));
		return this;
	}
});

/**
 * Auto applies on sliding-* menus.
 */
window.addEvent('domready', function() {
	$$('.mod_navigation').each(function(navigation) {
		var classes = navigation.getProperty('class').split(/\s/);
		var isSliding = false;
		var mode = 'direct'; // direct|fade|slide|bounce
		var hasDelayIn = false;
		var delayIn = 750;
		var delayOut = 200;
		var hasTransitionIn = false;
		var noTrail = false;
		var transitionIn = 'linear';
		var transitionOut = 'linear';
		var childrenToo = false;
		for (var c = classes.length - 1; c >= 0; c--) {
			if (classes[c].substr(0, 'sliding'.length) == 'sliding') {
				isSliding = true;
				var options = classes[c].split('-');
				for (var o = 1; o < options.length; o++) {
					switch (options[o]) {
					case 'direct':
						transitionIn = 'quad:out';
						transitionOut = 'quad:out';
						mode = 'direct';
						break;
					case 'fade':
						transitionIn = 'quad:in';
						transitionOut = 'quad:out';
						mode = 'fade';
						break;
					case 'slide':
						transitionIn = 'quad:out';
						transitionOut = 'quad:out';
						mode = 'slide';
						break;
					case 'bounce': 
						transitionIn = 'bounce:out';
						transitionOut = 'quad:out';
						mode = 'bounce';
						break;
					case 'notrail': 
						noTrail = true;
						break;
					case 'children': 
						childrenToo = true;
						break;
					default:
						var number = false;
						var transition = false;
						if (/^\d{1,6}ms$/.test(options[o])) {
							number = options[o].substring(-2).toInt();
						} else if (/^\d{1,3}s$/.test(options[o])) {
							number = 1000 * options[o].substring(-1).toInt();
						} else if (/^\d+$/.test(options[o])) {
							number = options[o].toInt();
						} else if (/^(linear|\w+)(:(in|out))?$/.test(options[o])) {
							transition = options[o];
						}
						if (number !== false) {
							if (hasDelayIn) {
								delayOut = number;
							} else {
								delayIn = number;
								hasDelayIn = true;
							}
						}
						if (transition !== false) {
							if (hasTransitionIn) {
								transitionOut = transition;
							} else {
								transitionIn = transition;
								hasTransitionIn = true;
							}
						}
						break;
					}
				}
			}
		}
		
		if (isSliding) {
			var menu = navigation.getFirst('ul');
			new MooDropMenu(menu, {
				onOpen: function(el){
					if (noTrail && el.getParents('.trail').length > 0) { return; }
				
					if (!el.isOpened)
					{
						el.pel.addClass('opened').setStyle('z-index', 1000);
						if (el.tweenMenu)
						{
							el.tweenMenu.cancel();
						}
						switch (mode) {
						case 'fade': 
							el.tweenMenu = new Fx.Tween(el, {duration: delayIn, transition: transitionIn});
							el.tweenMenu.start('opacity', 1);
							break;
						case 'slide':
						case 'bounce':
							el.setStyles({visibility: 'hidden', height: 'auto', paddingTop: '', paddingBottom: '', overflow: 'hidden'});
							var height = el.getSize().y
								+ el.getStyle('margin-bottom').toInt()
								+ el.getStyle('margin-top').toInt()
								- el.getStyle('padding-top').toInt()
								- el.getStyle('padding-bottom').toInt();
							el.setStyles({height: 0, visibility: ''});
							el.fade('show');
							el.tweenMenu = new Fx.Tween(el, {duration: delayIn, transition: transitionIn});
							el.tweenMenu.addEvent('complete', function() { el.setStyles({height: 'auto', overflow: ''}); });
							el.tweenMenu.start('height', height);
							break;
						case 'direct': default: el.fade('show'); break;
						}
						el.isOpened = true;
					}
				},
				onClose: function(el){
					if (noTrail && el.getParents('.trail').length > 0) { return; }
					
					el.pel.removeClass('opened').setStyle('z-index', 999);
					if (el.tweenMenu)
					{
						el.tweenMenu.cancel();
					}
					switch (mode) {
					case 'fade': 
						el.set('tween', {duration: delayOut, transition: transitionOut});
						el.fade('out');
						break;
					case 'slide':
					case 'bounce':
						el.setStyles({height: '', overflow: 'hidden'});
						el.tweenMenu = new Fx.Tween(el, {duration: delayOut, transition: transitionOut});
						el.tweenMenu.addEvent('complete', function() {
							el.setStyles({paddingTop: 0, paddingBottom: 0});
						});
						el.tweenMenu.start('height', 0);
						break;
					case 'direct': default: el.fade('hide'); break;
					}
					el.isOpened = false;
				},
				onInitialize: function(el){
					var parent = el.pel;
					if (parent.getStyle('position') != 'relative' && parent.getStyle('position') != 'absolute') {
						parent.setStyle('position', 'relative');
					}
					parent.setStyle('z-index', 999);

					if (noTrail && el.getParents('.trail').length > 0) {
						el.fade('show');
					}
					else
					{
						el.fade('hide');
					}
				},
				mouseoutDelay: 100,
				withChildren: childrenToo
			});
		}
	});
});

