/**
 * Ceravista
 * Author: Kim Biesbjerg
 */
var cvMenu = Class.create();

cvMenu.prototype = {
	
	setOptions: function(options)
	{
		this.options = {
			hideDelay:		.45,
			showDuration:	.4,
			hideDuration:	.2
		};
		Object.extend(this.options, options || {});
	},

	initialize: function(ul, options)
	{
		this.isIE6 = !window.XMLHttpRequest;
		this.ul = $(ul);
		this.setOptions(options);
		this.queue = new Array();
		this.setProperties();
		this.observers();
	},
	
	setProperties: function()
	{		
		// Add firstChild, lastChild classes
		$$('#' + this.ul.id, '#' + this.ul.id + ' ul').each(function(ul)
		{
			var count = $(ul).immediateDescendants('li').length;
			$(ul).down('li', 0).addClassName('firstChild');
			$(ul).down('li', (count-1)).addClassName('lastChild');
		});
		
		$(this.ul).setStyle({zIndex: this.ul.style.zIndex + 2});
		
		// For some reason it's necessary to hide the UL's backwards or IE6 & IE7 chokes!
		this.ul.getElementsBySelector('ul').reverse().invoke('hide');
	},
	observers: function()
	{
		// Hide menu on click
		Event.observe(document, 'click', function()
		{
			this.hideChildren(this.ul.down('li'));
		}.bind(this));
		
		this.ul.descendants().each(function(element, i)
		{	
			var ul = $(element).down('ul');
						
			// If has children
			if(element.tagName == 'LI' && $(element).down('UL') != undefined){
				
				
				// IE only
				if(this.isIE6){
					ul.setAttribute('id', 'ul' + i);
				}
				
				$(element).addClassName('hasChildren');
				
				Event.observe(element, 'mouseover', function(event){						
					this.removeHoverClass(element);
					if( ul.visible() ){
						clearTimeout( ul.getAttribute('timer') );
						this.unqueueHide(ul);
					} else {
						this.show(ul);
					}		

					
				}.bind(this));
				
				Event.observe(element, 'mouseout', function(event){					
					this.queueHide(ul);
					ul.setAttribute("timer", setTimeout(this.queueExecute.bind(this), this.options.hideDelay * 1000) );					
				}.bind(this));
			
			} else if(element.tagName == 'LI'){

				Event.observe(element, 'mouseover', function(){
					
					this.hideChildren(element);
					
				}.bind(this));				
	
			}
					
		}.bind(this));
		
	},
	
	removeHoverClass: function(obj)
	{
		var skip = $(obj).down('a');
		
		$(obj).up('ul').immediateDescendants('li').each(function(element, i){
			if(element.tagName == 'LI')
			{
				if($(element).down('a') != skip) // Do not remove current
				{
					$(element).down('a').removeClassName('hover');
				}
			}
		});
	},
	
	show: function(obj){		
		// Hide visible menus		
		if( !$(obj).visible() ){
			this.hideChildren($(obj).up('ul').down('li'));
		
			if(this.parent(obj))
			{
				new Effect.Parallel(
					[
						new Effect.BlindDown(obj, {sync: true}),
						new Effect.Appear(obj, {sync: true})
					],
					{
						duration: this.options.showDuration,
						beforeStart: function(){
							this.createIframe(obj);
							$(obj).previous('a').addClassName('hover');
						}
						.bind(this)
					}
				);		
				
			}
			else
			{
				new Effect.Appear(obj, {
					duration: this.options.showDuration * 0.75,
					beforeStart: function(){
						this.createIframe(obj);
						$(obj).previous('a').addClassName('hover');
					}.bind(this)
				});			
	
			}
		
		}	
	},
	
	hide: function(obj)
	{
		var obj = $(obj);
		new Effect.Fade(obj, {
			duration: this.options.hideDuration,
			afterFinish: function()
			{
				obj.previous('a').removeClassName('hover');
				this.hideIframe(obj);
			}
			.bind(this)
		});	
	},
	// Checks if element is parent ul
	parent: function(element)
	{
		try{
			var parent = $(element).up('ul').id == this.ul;
		} catch(e){
			var parent = false;
		}
		return parent;
	},
	// Takes an Element, traverses up to first UL parent, and hides all UL children of this parent
	hideChildren: function(parent)
	{

		// Notice reverse()? IE needs this to be able to hide all children properly
		$(parent).up().descendants('ul').reverse().each(function(ul, i){

			if(ul.tagName == 'UL' && $(ul).visible() ) //  
			{				
				$(ul).hide();
				this.unqueueHide(ul);
				$(ul).previous('a').removeClassName('hover');
				clearTimeout( ul.getAttribute('timer') );
				this.hideIframe(ul);
			}			
		}
		.bind(this));
	},
	queueHide: function(obj)
	{
		this.queue.push(obj);
	},
	unqueueHide: function(obj)
	{
		this.queue = this.queue.without(obj);
	},	
	queueExecute: function()
	{
		var obj = this.queue.shift();
		if(obj != undefined){
			obj.removeAttribute('timer');
			this.hide(obj);
		}
	},
	createIframe: function(obj)
	{
		if(this.isIE6){
			if($('iframe_' + obj.getAttribute('id')) == undefined){
				var iframe = document.createElement('iframe');
				iframe.id = 'iframe_' + obj.getAttribute('id');
				iframe.src = 'javascript:;';
				iframe.scrolling = 'no';
				iframe.style.position = 'absolute';
				iframe.style.zIndex = '1';
				iframe.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
				iframe.frameborder = '0';
				
				document.body.appendChild(iframe);
				
				// Element must be visible to get dimensions
				$(obj).show();
				Position.clone(obj, iframe);
				$(obj).hide();
			} else {
				$('iframe_' + obj.getAttribute('id')).show();
			}
		}
	},
	hideIframe: function(obj){
		if($('iframe_' + obj.getAttribute('id')) != undefined && this.isIE6){
			$('iframe_' + obj.getAttribute('id')).hide();
		}
	}
		
};
