var domReady = false;
window.addEvent('domready', function(){
	domReady = true;
	$$('li').each(function(element){
		element.addEvent('mouseover', function() {
			this.addClass('sfhover');
		});
		element.addEvent('mouseout', function() {
			this.removeClass('sfhover');
		});
	});
});

//Gets the width of text based on a supplied CSS class.
function maxTextWidth(textOrArray, textClass, dropElements){
	if(!$chk(textClass)){ var textClass = 'GetWidth';}
	if(!$chk(dropElements)){ var dropElements = ['ul'];}
	var width = 0;
	var spanElement = new Element('span', {'class':textClass,'styles':{'margin':'0','padding':'0','border':'0'}});
	spanElement.setStyle('whiteSpace', 'nowrap');
	document.body.adopt(spanElement);
	if(typeof(textOrArray)=='string'){
		spanElement.set('html', textOrArray);
		dropElements.each(function(elSelector){
			spanElement.getChildren(elSelector).each(function(tmpDrop){
				tmpDrop.dispose();
			}, this);
		}, this);
		width = spanElement.getSize().x;
	}else{
		$each(textOrArray, function(currentText){
			var tmpText = currentText;
			if(typeof(textOrArray)!='string'){tmpText = currentText.get('html');}
			spanElement.set('html', tmpText);
			dropElements.each(function(elSelector){
				spanElement.getChildren(elSelector).each(function(tmpDrop){
					tmpDrop.dispose();
				}, this);
			}, this);
			var tmpWidth = spanElement.getSize().x;
			if(width < tmpWidth){width=tmpWidth;}
		});
	}
	spanElement.dispose();
	return width;
}

function getInsideExtraWidth(element){
	return element.getSize().x-parseInt(element.getStyle('width'));
}

function getInsideExtraHeight(element){
	return element.getSize().y-parseInt(element.getStyle('height'));
}


function getOutsideExtraWidth(element){
	return parseInt(element.getStyle('margin-right'))+parseInt(element.getStyle('margin-left'));
}

function getOutsideExtraHeight(element){
	return parseInt(element.getStyle('margin-top'))+parseInt(element.getStyle('margin-bottom'));
}

function getExtraHeight(element){
	return getInsideExtraHeight(element)+getOutsideExtraHeight(element);
}

function getExtraWidth(element){
	return getInsideExtraWidth(element)+getOutsideExtraWidth(element);
}

function getExtraLeft(element){
	return parseInt(element.getStyle('padding-left'))+parseInt(element.getStyle('border-left'))+parseInt(element.getStyle('margin-left'));
}

function getExtraRight(element){
	return parseInt(element.getStyle('padding-right'))+parseInt(element.getStyle('border-right'))+parseInt(element.getStyle('margin-right'));
}

function getExtraTop(element){
	return parseInt(element.getStyle('padding-top'))+parseInt(element.getStyle('border-top'))+parseInt(element.getStyle('margin-top'));
}

function getExtraBottom(element){
	return parseInt(element.getStyle('padding-bottom'))+parseInt(element.getStyle('border-bottom'))+parseInt(element.getStyle('margin-bottom'));
}

var MooMenuSizer = new Class({
	Implements: [Options],
	options: {
		auto:true,
		makeVertical:false,	        //Means we have a vertical root level instead of horizontal
		applyToRootUL:false,	    //ROOT: apply width of contained LIs to UL. (FORCES MAKE VERTICAL)
		applyToRoot:'exact',        //apply width to root level LIs true, false, 'exact' (exact means size exactly to each li)
		applyToUL:true,	            //apply width of contained LIs to UL. A number supplied will indicate false until that depth.
		exactLI:true,				//if true this resizes to the exact content size
		alignToRoot:true,	        //Makes horizontal dropdown elements align to the left right under (or above) the root ul
		dropUp:false,	            //Sweets
		minWidth:20,	            //widths applied will never be lower than this number
		maxWidth:false,	            //-1 or false means no max, a positive integer will limit the max width
		extraWidth: 0,	            //extraWidth is added after width is calculated and is added to the width       
		selectors:['.navigation'],  //Should always point to the root ul itself.
		parentContainer: 'ul',
		nodeContainer: 'li',
		textClass:'GetWidth'
	},
	initialize: function(options){
		this.width = [];
		this.setOptions(options);
		if(this.options.applyToRootUL){this.options.makeVertical = true;}
		if(this.options.auto){
			this.checkFix();
		}
	},
	checkFix: function(){
		if(!domReady){
			this.checkFix.delay(100, this);
		}else{
			this.applyFix();
		}
	},
	applyFix: function(){
		this.options.selectors.each(function(SelectorString){
			$$(SelectorString).each(function(element){
				this.applyFixToNodes(element, 0, 0);
			}, this);
		}, this);
	},
	applyFixToNodes: function(element, depth, dropFrom){
		lis = element.getChildren(this.options.nodeContainer);
		var width = maxTextWidth(lis, this.options.textClass, this.options.dropForCalculation);
		if(this.options.maxWidth !== false && this.options.maxWidth > 0 && width > this.options.maxWidth){
			width = this.options.maxWidth;
		}else if(width < this.options.minWidth){
			width = this.options.minWidth;
		}
		//alert((getInsideExtraWidth(lis[0])+getInsideExtraWidth(lis[0].getElement('a'))+getOutsideExtraWidth(lis[0])));
		this.setPositionOfUL(element, depth, dropFrom, width+(getInsideExtraWidth(lis[0])+getOutsideExtraWidth(lis[0])));
		this.recursiveResizeListElements(lis, depth, width, getInsideExtraWidth(lis[0].getElement('a'))+getOutsideExtraWidth(lis[0].getElement('a')));
	},
	setPositionOfUL: function(element, depth, dropFrom, resizeWidth){
		if(depth > 0){
			if((this.options.applyToUL === true) || (this.options.applyToUL!==false && depth>=(this.options.applyToUL+1))){
				element.setStyle('width', (resizeWidth)+'px');
			}
			var link = dropFrom.getElement('a');
			if(this.options.applyToUL===true || (this.options.applyToUL!==false && depth>=(this.options.applyToUL+1))){
				if((depth>1 || this.options.makeVertical)){
					if(this.options.applyToUL===true || (depth)!==(this.options.applyToUL+1)){
						element.setStyle('margin-left', link.getPosition(dropFrom).x+link.getSize().x+parseInt(link.getStyle('margin-right')));
						if(this.options.dropUp){
							element.setStyle('margin-top', (element.getSize().y-parseInt(dropFrom.getStyle('padding-top')))*-1);
						}else{
							element.setStyle('margin-top', (link.getPosition(dropFrom).y+link.getSize().y+parseInt(link.getStyle('margin-top')))*-1);
						}
					}else{
						element.setStyle('margin-left', (dropFrom.getPosition(link).x));
					}
				}else if(this.options.dropUp){
					element.setStyle('margin-top', (element.getSize().y+dropFrom.getSize().y-parseInt(dropFrom.getStyle('padding-top')))*-1);
				}
			}else if(this.options.applyToUL===false || (this.options.applyToUL!==false && depth<(this.options.applyToUL+1))){
				if(this.options.alignToRoot === true){
					element.setStyle('margin-top', (link.getPosition(dropFrom).y-getExtraHeight(dropFrom))*-1);
					element.setStyle('margin-left', (dropFrom.getPosition(dropFrom.getParent()).x+getExtraLeft(dropFrom))*-1);
				}else{
					element.setStyle('margin-top', (link.getPosition(dropFrom).y+link.getSize().y+parseInt(link.getStyle('margin-top')))*-1);
					element.setStyle('margin-left', (dropFrom.getPosition(link).x));
				}
			}
		}else if(this.options.applyToRootUL){
			element.setStyle('width', (resizeWidth)+'px');
		}
	},
	recursiveResizeListElements: function(lis, depth, width, paddingWidth){
		lis.each(function(liElement){
			if(depth>0||this.options.applyToRoot===true){
				if(this.options.exactLI && (this.options.applyToUL===false || (this.options.applyToUL!==true && depth<(this.options.applyToUL+1)))){
					liElement.setStyle('width', (maxTextWidth(liElement.get('html'), this.options.textClass, this.options.dropForCalculation)+paddingWidth));
				}else{
					liElement.setStyle('width', (width+paddingWidth)+'px');
				}
			}else if(depth===0&&this.options.applyToRoot==='exact'){
				liElement.setStyle('width', maxTextWidth(liElement.get('html'), this.options.textClass, this.options.dropForCalculation)+paddingWidth);
			}
			var ul = liElement.getElement(this.options.parentContainer);
			if($defined(ul)){
				this.applyFixToNodes(ul, depth+1, liElement);
			}
		}, this);
	}
});