//
// Copyright (c) 2007-2008 Stardock Systems, Inc.
// Author: Andrew Powell, 10.30.07
// Version 1.0
//

Sd.Menus = Class.create();
Sd.Menus.prototype =
{

}

Sd.Menus.Registry = [];
Sd.Menus.slideLength = 200;
Sd.Menus.hideDelay = 500;
Sd.Menus.activityDelay = 2000;
Sd.Menus.minCPUResolution = 10;
Sd.Menus.items = [];

Sd.MenusScript = true;
Sd.MenusTimeout = null;

Sd.Menus.Menu = Class.create();
Sd.Menus.Menu.prototype =
{
	initialize: function (triggerid, id, dir, customCssClassPrefix, immediate)
	{
		if(!$id('StardockMenuCss')) Sd.Menus.initCss();

		this.ie = document.all ? 1 : 0;
		this.ns4 = document.layers ? 1 : 0;
		this.dom = document.getElementById ? 1 : 0;
		this.customCssClassPrefix = (customCssClassPrefix == null) ? "" : customCssClassPrefix;
		
		//if true, the menu will render immediately after the target element.
		this.immediate = (immediate == null) ? false : immediate;
		
		this.animate = true;
		
		this.onMenuShow = function(){ };
		this.onMenuVisible = function(){ };
		this.onMenuHide = function(){ };
		this.onMenuHidden = function(){ };
		
		if (this.ie || this.ns4 || this.dom)
		{
			this.triggerid = triggerid;
			this.trigger = $id(this.triggerid);
			this.id = id;
			this.dir = dir;
			this.orientation = dir == "left" || dir == "right" ? "h" : "v";
			this.dirType = dir == "right" || dir == "down" ? "-" : "+";
			this.hideTimer = false;
			this.aniTimer = false;
			this.open = false;
			this.over = false;
			this.startTime = 0;
			this.height = 10;
			this.width = 1;
			this.dim = this.orientation == "h" ? this.width : this.height;
			this.gRef = "Sd.Menus_" + id;
			eval(this.gRef+"=this");
			Sd.Menus.Registry[id] = this;

			if(this.trigger)
			{
				this.triggerpos = Sd.Common.getElementPos(this.trigger);

			}

			this.load();

		}
	},

	addItem: function(link, label, onclick, type)
	{
		var container = this.container;
		if(container == null || !container) return;

		var type = (type == null) ? 'a' : type;
		var item = document.createElement(type);

		if(type == 'a')
			item.href = link;

		item.innerHTML = label;
		item.onmouseover = new Function("Sd.Menus.clearTimeout('" + this.id + "')");
		item.onmouseout = new Function("Sd.Menus.hideMenu('" + this.id + "')");

		if(onclick && onclick != null && onclick != '')
		{
			if(typeof(onclick) == 'function')
				item.onclick = onclick;
			else
				item.onclick = function(){ eval(onclick); }
		}

		this.menuItems.appendChild(item);

		var width = this.getElementWidth(item);
		var height = this.getElementHeight(item);

		if(width > this.width) this.width = width + 13;

		this.height += height;

		this.recalcSize(container, width, height);

		return item;

	},

	addHeader: function(text, addToTop)
	{
		var addToTop = (addToTop == null) ? true : addToTop;
		var container = this.container; //document.getElementById(this.id + 'MenuContainer');
		if(container == null) return;

		var header = document.createElement('div');
		header.innerHTML = text;
		header.className = 'StardockMenu_MenuHeader';
		header.onmouseover = new Function("Sd.Menus.clearTimeout('" + this.id + "')");
		header.onmouseout = new Function("Sd.Menus.hideMenu('" + this.id + "')");

		if(this.menuItems.firstChild && addToTop == true)
			this.menuItems.insertBefore(header, this.menuItems.firstChild);
		else
			this.menuItems.appendChild(header);

		var width = this.getElementWidth(header);
		var height = this.getElementHeight(header);

		if(width > this.width) this.width = width + 13;

		this.height += height;

		this.recalcSize(container, width, height);

		return header;

	},

	addSeparator: function()
	{

	},

	recalcSize: function(container, width, height)
	{
		container.style.height = this.height + 'px';
		container.style.width = this.width + 'px';
		container.style.clip = 'rect(0px ' + (this.width) + 'px ' + (this.height) + 'px 0px)';

		var docRect = this.getDocumentRect();

		if(this.triggerpos.left > docRect.width || (this.triggerpos.left + this.width) > docRect.width)
		{
			//var difference = (this.triggerpos.left + this.width) - docRect.width;
			this.triggerpos.left = docRect.width - this.width - 10;
			this.container.style.left = (this.triggerpos.left) + 'px';

		}

		this.dim = this.orientation == "h" ? this.width : this.height;
		this.homePos = eval("0" + this.dirType + this.dim);

		this.accelConst = (this.outPos - this.homePos) / Sd.Menus.slideLength / Sd.Menus.slideLength;

		//set the correct initial state, again, since we're changing it's dimensions.
		this.endSlide();
	},

	reposition: function()
	{
		//var trigger = document.getElementById(this.triggerid);
		if(this.trigger)
		{
			this.triggerpos = Sd.Common.getElementPos(this.trigger);
			this.container.style.left = (this.triggerpos.left) + 'px';
			this.container.style.top = (this.triggerpos.top + this.triggerpos.height) + 'px';

			var docRect = this.getDocumentRect();

			if(this.triggerpos.left > docRect.width || (this.triggerpos.left + this.width) > docRect.width)
			{
				this.triggerpos.left = docRect.width - this.width - 10;
				this.container.style.left = (this.triggerpos.left) + 'px';
			}

		}

		this.container.style.zIndex = 99999999;

	},

	load: function()
	{
		var containerDiv = document.createElement('div');
		var contentDiv = document.createElement('div');
		var menuitemsDiv = document.createElement('div');

		containerDiv.id = this.id + 'MenuContainer';
		containerDiv.className = 'StardockMenu_Container' + (this.customCssClassPrefix =='' ? '': (' ' + this.customCssClassPrefix + '_Container'));
		//containerDiv.style.border = '1px solid red';
		containerDiv.style.position = 'absolute';
		containerDiv.style.zIndex = 9999;
		containerDiv.style.left = (this.triggerpos.left) + 'px';
		containerDiv.style.top = (this.triggerpos.top + this.triggerpos.height) + 'px';
		containerDiv.style.overflow = "hidden";
		containerDiv.style.whiteSpace = 'nowrap';

		contentDiv.id = this.id + 'MenuContent';
		contentDiv.className = 'StardockMenu_Menu' + (this.customCssClassPrefix =='' ? '': (' ' + this.customCssClassPrefix + '_Menu'));
		contentDiv.style.position = 'absolute';

		menuitemsDiv.id = this.id + 'MenuItems';
		menuitemsDiv.className = 'StardockMenu_MenuItems' + (this.customCssClassPrefix =='' ? '': (' ' + this.customCssClassPrefix + '_Container'));

		contentDiv.appendChild(menuitemsDiv);
		containerDiv.appendChild(contentDiv);

		if(!this.immediate)
			document.body.appendChild(containerDiv);
		else
			document.body.insertBefore(containerDiv, document.body.firstChild);
			
			//this.trigger._parent().insertBefore(containerDiv, this.trigger);

		this.container = containerDiv; //obj1
		this.menu = contentDiv; //obj2
		this.menuItems = menuitemsDiv;
		this.style = this.ns4 ? this.menu : this.menu.style;
		this.homePos = eval("0" + this.dirType + this.dim);
		this.outPos = 0;
		this.accelConst = (this.outPos - this.homePos) / Sd.Menus.slideLength / Sd.Menus.slideLength;

		// set event handlers.
		if (this.ns4) this.menu.captureEvents(Event.MOUSEOVER | Event.MOUSEOUT);
		this.menu.onmouseover = new Function("Sd.Menus.clearTimeout('" + this.id + "')");
		this.menu.onmouseout = new Function("Sd.Menus.hideMenu('" + this.id + "')");

		//set initial state
		this.endSlide();

	},

	startSlide: function(open)
	{
		this[open ? "onactivate" : "ondeactivate"]();
		this.open = open;
		if (open) this.setVisibility(true);
		
		if(this.animate == true)
		{
			this.startTime = (new Date()).getTime();
			this.aniTimer = window.setInterval(this.gRef + ".slide()", Sd.Menus.minCPUResolution);
		}
		else
		{
			this.endSlide();
		}
	},

	slide: function()
	{
		var elapsed = (new Date()).getTime() - this.startTime;
		if (elapsed > Sd.Menus.slideLength)
			this.endSlide();
		else
		{
			var d = Math.round(Math.pow(Sd.Menus.slideLength-elapsed, 2) * this.accelConst);
			if (this.open && this.dirType == "-") d = -d;
			else if (this.open && this.dirType == "+") d = -d;
			else if (!this.open && this.dirType == "-") d = -this.dim + d;
			else d = this.dim + d;
			this.moveTo(d);
		}
	},

	endSlide: function()
	{
		this.aniTimer = window.clearTimeout(this.aniTimer);
		this.moveTo(this.open ? this.outPos : this.homePos);
		if (!this.open) 
		{
			this.setVisibility(false);
			this.onMenuHidden(this);
		}

		if ((this.open && !this.over) || (!this.open && this.over))
			this.startSlide(this.over);
		else
			this.onMenuVisible(this);
	},

	setVisibility: function(bShow)
	{
		var s = this.ns4 ? this.container : this.container.style;

		s.visibility = bShow ? "visible" : "hidden";

	},

	moveTo: function(p)
	{
		this.style[this.orientation == "h" ? "left" : "top"] = this.ns4 ? p : p + "px";
	},

	getPos: function(c)
	{
		return parseInt(this.style[c]);
	},

	onactivate: function() { },
	ondeactivate: function() { },

	getElementHeight: function(elem)
	{
		xPos = elem.offsetHeight;
		return xPos;
	},

	getElementWidth: function(elem)
	{
		xPos = elem.offsetWidth;
		return xPos;
	},

	getDocumentRect: function()
	{
		var w = window;
		var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;

		return {
			left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),
			top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),
			width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),
			height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)
		};
	}
}

	// Makes a Stardock.Menu's items not be cut off in Firefox.
	Sd.Menus.recalcMenuSize = function( menu, item ) 
	{
	   var width = menu.getElementWidth(item)
	   var height = menu.getElementHeight(item);
	
	   if(width > menu.width) menu.width = width + 13;
	
	   menu.height += height;
	
	   menu.recalcSize(menu.container, width, height);		
	};

	// *** Function : showMenu
	Sd.Menus.showMenu = function(id)
	{
		var reg = Sd.Menus.Registry;
		var obj = Sd.Menus.Registry[id];
		if(!obj || typeof(obj) == 'undefined' || obj == null) return;
		if (obj.container)
		{
			obj.reposition();
			obj.over = true
			for (menu in reg) if (id != menu)
			{
				Sd.Menus.hide(menu);
				var menuObj = Sd.Menus.Registry[menu];
				if(menuObj && menuObj.onMenuHide) menuObj.onMenuHide(menu);
			}
			
			if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer); }
			if (!obj.open && !obj.aniTimer) 
				reg[id].startSlide(true);

			obj.onMenuShow(obj);

			Sd.MenusTimeout = window.setTimeout("Sd.Menus.hideMenu('" + id + "')", Sd.Menus.activityDelay);
		}
	}

	Sd.Menus.clearTimeout = function(id)
	{
		var reg = Sd.Menus.Registry;
		var obj = Sd.Menus.Registry[id];
		if (obj.hideTimer) { reg[id].hideTimer = window.clearTimeout(reg[id].hideTimer); }
		if(Sd.MenusTimeout) window.clearTimeout(Sd.MenusTimeout);
	}

	Sd.Menus.hideMenu = function(id)
	{
		var obj = Sd.Menus.Registry[id];
		if (obj.container)
		{
			obj.onMenuHide(obj);
			if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
			obj.hideTimer = window.setTimeout("Sd.Menus.hide('" + id + "')", Sd.Menus.hideDelay);
		}
	}

	Sd.Menus.hideAll = function()
	{
		var reg = Sd.Menus.Registry;
		for (menu in reg)
		{
			Sd.Menus.hide(menu);
			if (menu.hideTimer) window.clearTimeout(menu.hideTimer);
		}
	}

	Sd.Menus.hide = function(id)
	{
		var obj = Sd.Menus.Registry[id];
		obj.over = false;
		if (obj.hideTimer) window.clearTimeout(obj.hideTimer);
		obj.hideTimer = 0;
		if (obj.open && !obj.aniTimer) obj.startSlide(false);
	}

	Sd.Menus.initCss = function(id)
	{
		//initialize the default css for the menu. These shouldn't be overriden. Instead the customCssClassPrefix parameter
		//should be used in the menu constructor.
		var css =
			'.StardockMenu_Menu { margin-right:1px; margin-bottom:1px; background-color:transparent; }' +
			'.StardockMenu_MenuItems { margin-right:1px; margin-bottom:1px; border:1px solid #333333; background-color: white; }' +
			'.StardockMenu_Menu a { color:#333333; display:block; padding:2px 10px; text-decoration:none; background-color:transparent; }' +
			'.StardockMenu_Menu a:hover { background-color:#666666; color:#ffffff; }' +
			'.StardockMenu_Container { margin-top: 2px; }' +
			'.StardockMenu_MenuHeader { color:#ffffff; background-color:#333333; padding:2px 10px; font-size: 11px; }';

		var head = document.getElementsByTagName('head')[0];
		var styleTag = document.createElement('style');
		styleTag.id = 'StardockMenuCss';

		styleTag.setAttribute("type", "text/css");

		if(styleTag.styleSheet)	// IE
		{
			styleTag.styleSheet.cssText = css;
			head.insertBefore(styleTag, head.childNodes(0));
		}
		else	// w3c
		{
			var cssText = document.createTextNode(css);
			styleTag.appendChild(cssText);
			head.insertBefore(styleTag, head.childNodes[0]);
		}
		
	}



