//
//  menu.js
//  Menu Javascript Library for Sparkle
//
//  Created by Daniele Trambusti
//  Copyright (c) 2014 River. All rights reserved.
//

function MenuItem() {
	this.parent = undefined;
	this.element = undefined;
	this.data = undefined;
	this.width = 0;
	this.height = 0;
	this.currentAnimation = 0;
}

MenuItem.prototype.createMenuItem = function (itemData, parentElement) {
	var itemElement = $("<li></li>");
	this.setData(itemData, itemElement, parentElement);
	
	if(itemData.submenu != undefined) {
		this.subMenu = createMenu(itemData.submenu);
		this.subMenu.createMenu(itemData.submenu, itemElement);
	}
	
	this.addEvents();

	return itemElement;
}

MenuItem.prototype.attachMenuItem = function (itemData, itemElement) {
	var item = this;
	item.setData(itemData, itemElement);

	if(itemData.submenu != undefined) {
		$(itemElement).children("ul").each(
			function() {
				item.subMenu = createMenu(itemData.submenu);
				item.subMenu.attachMenu(itemData.submenu, this);
			}
		);
	}

	item.addEvents();

	return itemElement;
}

MenuItem.prototype.setData = function (itemData, itemElement, parentElement) {
	this.data = itemData;
	this.element = itemElement;
	if(parentElement != undefined) {
		$(parentElement).append(itemElement);
		$(itemElement).append(this.menuContent());
	}
	else {
		parentElement = $(itemElement).parent();
	}
	var parent = $(parentElement).data("itemData");
	this.parent = parent != undefined ? parent : undefined;
	if($(itemElement).attr("id") == undefined && itemData.id != undefined) {
		$(itemElement).attr("id", itemData.id);
	}
	if($(itemElement).attr("class") == undefined && itemData.cssClass != undefined) {
		$(itemElement).attr("class", itemData.cssClass);
	}
	if(itemData.position != undefined) {
		$(itemElement).css("marginLeft", itemData.position.x);
		$(itemElement).css("marginTop", itemData.position.y);
	}
	if(itemData.size != undefined) {
		$(itemElement).css("width", itemData.size.width);
		$(itemElement).css("height", itemData.size.height);
	}
	$(itemElement).data("itemData", this);
}

MenuItem.prototype.addEvents = function () {
	if(this.data.hover != undefined) {
		var itemElement = this.element;
		$(itemElement).hover(this.hover);
	}
	else if(this.data.hover_in != undefined && this.data.hover_out != undefined) {
		var itemElement = this.element;
		$(itemElement).hover(this.hoverIn, this.hoverOut);
	}
}

MenuItem.prototype.updateDefaults = function (itemElement) {
	if(itemElement == undefined) {
		itemElement = this.element;
	}

	$(itemElement).children("ul").each(
		function() {
			updateMenuDefaults(this);
		}
	);

	var menuContent = $(itemElement).find(".menu-content");
	this.width = $(menuContent).width() + 1;
	this.height = $(menuContent).height();
}

MenuItem.prototype.setDefaultSize = function (itemElement) {
	if(itemElement == undefined) {
		itemElement = this.element;
	}

	$(itemElement).children("ul").each(
		function() {
			setMenuDefaultSize(this);
		}
	);

	$(itemElement).find(".menu-content").width(this.width);
	$(itemElement).find(".menu-content").height(this.height);
}

MenuItem.prototype.getAnimationProperties = function (properties) {
	var animationProperties = jQuery.extend({}, properties);
	if(animationProperties["width"] == "final") {
		animationProperties["width"] = this.width;
	}
	if(animationProperties["height"] == "final") {
		animationProperties["height"] = this.height;
	}
	
	if(animationProperties["min-width"] == "final") {
		animationProperties["min-width"] = this.width;
	}
	if(animationProperties["min-height"] == "final") {
		animationProperties["min-height"] = this.height;
	}
	return animationProperties;
}

MenuItem.prototype.animate = function (event, delay) {
	var item = this;
	++item.currentAnimation;
	var itemElement = item.element;

	// Before
	if(item.data[event].before != undefined) {
		item.before(item.getAnimationProperties(item.data[event].before));
	}

	// Animation
	if(delay == undefined) {
		delay = item.data[event].delay;
	}
	if(delay != undefined) {
		var currentAnimation = item.currentAnimation;
		setTimeout(
			function () {
				if(currentAnimation == item.currentAnimation) {
					$(itemElement).stop();
					$(itemElement).animate(
						item.getAnimationProperties(item.data[event].properties),
						item.data[event].animate == true ? item.data[event].duration : 0,
						function() {
							item.after(item.getAnimationProperties(item.data[event].after))
						}
					);
				}
			},
			delay
		);
	}
	else {
		$(itemElement).stop();
		$(itemElement).animate(
			item.getAnimationProperties(item.data[event].properties),
			item.data[event].animate == true ? item.data[event].duration : 0,
			function() {
				item.after(item.getAnimationProperties(item.data[event].after))
			}
		);
	}
	
	// Content
	if(item.data[event].content != undefined) {
		delay = item.data[event].content.delay;
		item.animateContent(item.data[event].content.event, delay);
	}

	// Submenu
	if(item.data[event].submenu != undefined) {
		var subMenuEvent = item.data[event].submenu.event;
		delay = item.data[event].submenu.delay;
		if(item.subMenu != undefined) {
			if(typeof item.subMenu[subMenuEvent] == "function") {
				if(delay != undefined) {
					var currentAnimation = item.subMenu.currentAnimation;
					setTimeout(
						function () {
							if(currentAnimation == item.subMenu.currentAnimation) {
							   item.subMenu[subMenuEvent].call(item.subMenu.element);
							}
						},
						delay
					);
				}
				else {
					item.subMenu[subMenuEvent].call(item.subMenu.element);
				}
			}
			else {
				item.subMenu.animate(
					subMenuEvent,
					delay,
					function() {
						item.subMenu.after(item.getAnimationProperties(item.subMenu[subMenuEvent].after));
					}
				);
			}
		}
	}
}

MenuItem.prototype.animateContent = function (event, delay) {
	var item = this;
	if(delay == undefined) {
		delay = item.data.content[event].delay;
	}
	if(delay != undefined) {
		var currentAnimation = this.currentAnimation;
		setTimeout(
			function () {
				if(currentAnimation == item.currentAnimation) {
					item.doAnimateContent(event);
				}
			},
			delay
		);
	}
	else {
		item.doAnimateContent(event);
	}
}

MenuItem.prototype.doAnimateContent = function (event) {
	var item = this;
	var itemElement = Element = item.element;
	var contentElement = $(itemElement).find(".menu-content");
	var eventData = item.data.content[event];
	$(contentElement).stop();
	$(contentElement).animate(
		item.getAnimationProperties(eventData.properties),
		eventData.animate == true ? eventData.duration : 0,
		function() {
			if(eventData.after != undefined) {
				$(this).css(eventData.after);
			}
		}
	);
	for(var key in eventData) {
		if(key.indexOf('child:') == 0) {
			var index = parseInt(key.substr(6));
			var child = $(contentElement).children().eq(index);
			if(eventData[key]['tag'] != undefined) {
				child = $(child).find(eventData[key]['tag']);
			}
			$(child).stop();
			$(child).animate(
				item.getAnimationProperties(eventData[key].properties),
				eventData.animate == true ? (eventData[key].duration != undefined ? eventData[key].duration : eventData.duration) : 0,
				function() {
					if(eventData[key].after != undefined) {
						$(this).css(eventData[key].after);
					}
				}
			);
		}
	}
}

MenuItem.prototype.before = function (properties) {
	if(properties != undefined) {
		$(this.element).css(properties);
	}
}

MenuItem.prototype.after = function (properties) {
	if(properties != undefined) {
		$(this.element).css(properties);
	}
}

MenuItem.prototype.hover = function () {
	var item = $(this).data("itemData");
	item.animate("hover");
}

MenuItem.prototype.hoverIn = function () {
	var item = $(this).data("itemData");
	item.animate("hover_in");
}

MenuItem.prototype.hoverOut = function () {
	var item = $(this).data("itemData");
	item.animate("hover_out");
}

MenuItem.prototype.show = function () {
	var item = $(this).data("itemData");
	show(this);
	item.animate("show");
}

MenuItem.prototype.hide = function () {
	var item = $(this).data("itemData");
	item.animate("hide");
}

MenuItem.prototype.menuContent = function () {
	var content =
	"<div class=\"menu-content\">" +
		"<div class=\"menu-label\">" +
			this.data.content.label +
		"</div>" +
	"</div>";
	return content;
}

function Menu() {
	this.items = new Array();
}

Menu.prototype = new MenuItem();
Menu.prototype.createMenu = function (menuData, parentElement) {
	var menuElement = $("<ul></ul>");
	this.setData(menuData, menuElement, parentElement);

	for(var idx in menuData.items) {
		var itemData = menuData.items[idx];
		var item = createMenuItem(itemData);
		item.createMenuItem(itemData, menuElement);
		this.items.push(item);
	}

	this.addEvents();

	return menuElement;
}

Menu.prototype.attachMenu = function (menuData, menuElement) {
	var menu = this;
	menu.setData(menuData, menuElement);

	if(menuData.items != undefined) {
		var idx = 0;
		$(menuElement).children("li").each(
			function() {
				if(idx < menuData.items.length) {
					var itemData = menuData.items[idx++];
					var item = createMenuItem(itemData);
					item.attachMenuItem(itemData, this);
					menu.items.push(item);
				}
				else {
					// Error
				}
			}
		);
	}

	menu.addEvents();

	return menuElement;
}

Menu.prototype.updateDefaults = function (menuElement) {
	if(menuElement == undefined) {
		menuElement = this.element;
	}

	var menu = this;
	var vertical = menu.data.vertical != undefined ? menu.data.vertical : false;
	menu.width = 0;
	menu.height = 0;
	$(menuElement).children("li").each(
		function() {
			updateMenuDefaults(this);
			var item = $(this).data("itemData");
			if(vertical) {
			   menu.height += item.height;
				if(item.width > menu.width) {
					menu.width = item.width;
				}
			}
			else {
				menu.width += item.width;
				if(item.height > menu.height) {
					menu.height = item.height;
				}
			}
	   }
	);
}

Menu.prototype.setDefaultSize = function (menuElement) {
	if(menuElement == undefined) {
		menuElement = this.element;
	}

	$(menuElement).children("li").each(
		function() {
			setMenuDefaultSize(this);
	   }
	);
}

Menu.prototype.menuContent = function () {
	return this.data.label;
}

Menu.prototype.animateContent = function (event, delay) {
	for(var idx in this.items) {
		var item = this.items[idx];
		item.animateContent(event, delay);
	}
}

function createMenuItem(itemData) {
	var itemClass = itemData != undefined && itemData.menuItemClass != undefined ? itemData.menuItemClass : "MenuItem";
	return new window[itemClass]();
}

function createMenu(menuData) {
	var menuClass = menuData != undefined && menuData.menuClass != undefined ? menuData.menuClass : "Menu";
	return new window[menuClass]();
}

function setupMenu(menuElement) {
	menuData = getMenuData(menuElement);
	if(menuData == undefined) {
		return false;
	}
	var itemData = menuData.items;
	var menu = createMenu(menuData);
	var parentElement = $(menuElement).parent();
	var parent = $(parentElement).data('itemData');
	if(parent != undefined) {
		parent.subMenu = menu;
	}
	menu.setData(menuData, menuElement);
	menu.addEvents();

	var res = true;
	$(menuElement).children("li").each(
		function() {
			var item = createMenuItem(itemData);
			item.setData(itemData, this);
			item.addEvents();
			menu.items.push(item);

			$(this).children("ul").each(
				function () {
					res = setupMenu(this);
					if(!res) {
						return false;
					}
				}
			);
			if(!res) {
				return false;
			}
		}
	);
	return res;
}

function getMenuData(menuElement) {
	var menuData = undefined;
	var menuClasses = $(menuElement).attr('class').split(/\s+/);
	$.each(menuClasses, function(index, menuClass) {
		menuData = getMenuDataForClass(menuClass);
		if(menuData != undefined) {
		   return false;
		}
	});
	return menuData;
}

var menuClasses = {};

function getMenuDataForClass(menuClass) {
	return menuClasses[menuClass];
}

function registerMenuClass(menuClass, menuData) {
	menuClasses[menuClass] = menuData;
}

function initMenu(menuElement) {
	if(!setupMenu(menuElement)) {
		return false;
	}
	return true;
}

function updateMenuDefaults(itemElement) {
	var item = $(itemElement).data("itemData");
	item.updateDefaults(itemElement);
}

function setMenuDefaultSize(itemElement) {
	var item = $(itemElement).data("itemData");
	item.setDefaultSize(itemElement);
}

function showRaw(element) {
	$(element).each(
		function() {
			$(this).css("display", "block");
			$(this).css("*display", "inline");
			$(this).children().each(
				function() {
					showRaw(this);
				}
			);
			var w = $(this).width();
			var h = $(this).height();
			if($(this).width() == 0) {
				$(this).css("width", "initial");
			}
			if($(this).height() == 0) {
				$(this).css("height", "initial");
			}
		}
	);
}

function show(element) {
	$(element).each(
		function() {
			if($(this).css("display") == "none") {
				$(this).css("display", "block");
				$(this).css("*display", "inline");
			}
			$(this).children().each(
				function() {
					if($(this).css("display") == "none" && $(this).css("visibility") == "visible") {
						$(this).css("display", "block");
						$(this).css("*display", "inline");
					}
				}
			);
		}
	);
}