define(['scripts/knockout-3.3.0','scripts/ACTComponent.js', "scripts/ACTUtils", "jqx/jqxtooltip"], function(ko, ACTComponent, ACTUtils) {

	var elementWithContextMenuOpen = null;

	function ButtonWithMenuComponentViewModel(params, element) {
		var self = this;
		var ENTRY_SEPARATOR = "__SEP__";

		self.base = new ACTComponent($(element), params);

		self.name = ko.observable();
		self.nameWithoutEllipsis = "";
		self.icon = ko.observable();
		self.topRightInformation = ko.observable();
		self.backColor = ko.observable();
		self.menuEntries = ko.observableArray([]);
		self.openMenuImage = ko.observable();

		self.tooltip = "";
		self.tooltipShowDelay = 500;

		self.openAnimationDuration = 100;
		self.backgroundColor = "#ffffff";
		self.hoverBackgroundColor = "#eeeeee";

		self.speedTitle = 2;

		var $buttonComp     = $(element).find(".buttonWithMenuComp");
		var $text           = $(element).find(".text");
		var $title          = $(element).find(".title");
		var $openMenuButton = $(element).find(".openMenuButton");
		var $trInfo         = $(element).find(".trInfo");
		var $menu           = $(element).find(".menu");
		var $menuEntries    = $menu.children();
		var $jqxTooltipElement;

		self.base.onRefresh = function(obj) {
			if (obj.TriggerClick) {
				$buttonComp.trigger("click");
				return;
			}

			params.ready(false);

			self.name(obj.Name);
			self.openMenuImage(obj.OpenMenuImage);
			self.nameWithoutEllipsis = obj.Name;
			self.icon(obj.Icon);
			self.topRightInformation(obj.TopRightInformation);

			self.backgroundColor = obj.BackgroundColor;
			self.hoverBackgroundColor = obj.HoverBackgroundColor;
			self.backColor(self.backgroundColor);
			if (obj.TextColor) $(element).find(".title").css("color", obj.TextColor);

			self.MenuEntryClicked = obj.MenuEntryClicked;
			self.MainClicked  = obj.MainClicked;

			self.base.addCallbackX(self, "menuClick", "MenuEntryClicked");
			self.base.addCallbackX(self, "realMainClick", "MainClicked");

			$(element).attr("keywords", obj.KeyWords);

			self.tooltip = obj.Tooltip;
			if (!obj.Tooltip || obj.Tooltip == "") {
				self.DestroyTooltip($(element));
			} else {
				self.CreateTooltip($(element), self.tooltip, self.tooltipShowDelay);
			}

			self.menuEntries([]);
			// we do the css here cause the element's DOM position will change
			if (obj.MenuEntries && obj.MenuEntries.length != 0) {
				for (var i = 0; i < obj.MenuEntries.length; i++) {
					var menuEntry = obj.MenuEntries[i];
					if (menuEntry == ENTRY_SEPARATOR)
						continue;

					var borderBottom = "0";
					if (i <= obj.MenuEntries.length) {
						var nextEntry = obj.MenuEntries[i+1];
						if (nextEntry == ENTRY_SEPARATOR)
							borderBottom = "1px solid #c2c2c2";
					}

					self.menuEntries.push({
						value: obj.MenuEntries[i],
						borderBottom: borderBottom,
						mouseenter: function(data, event) { $(event.target).css("color", "#ffffff"); },
						mouseleave: function(data, event) { $(event.target).css("color", "#c2c2c2"); },
						click: function(data, event) { self.menuClick($(event.target).text()); },
					});
				}
				$openMenuButton.show();
			} else {
				$openMenuButton.hide();
			}

			self.UpdateEllipsis();
			params.ready(true);
		}

		self.UpdateEllipsis = function() {
			var newText = ACTUtils.ApplyEllipsis($title, self.nameWithoutEllipsis);
			self.name(newText);
		}

		// we can to compute title position and ellipsis only when we got the right dimension
		var resizeIndex = params.baseModel.resizeFunctions.length;
		params.baseModel.resizeFunctions[resizeIndex] = function(height,width) {
			if (!$text.is(":visible"))
				return;
			self.UpdateEllipsis();

			// title position
			$text.css("left", ($buttonComp.width() - $title.width()) * 0.5);

			// setTimeout to not change the array when exploring it
			setTimeout(function() {
				// no need to stay in resizeFunctions cause the size of this component won't change
				params.baseModel.resizeFunctions.splice(resizeIndex, 1);
			}, 0);
		}

		self.CreateTooltip = function(element ,content, showDelay) {
			if (content && content != "") {
				self.tooltipActivated = true;
				self.currentTooltipElement = element;

				ACTUtils.CreateTooltip(element, content, false, {showDelay:showDelay});
			} }

		self.DestroyTooltip = function() {
			if (self.tooltipActivated) {
				self.tooltipActivated = false;
				self.currentTooltipElement.jqxTooltip("destroy");
			}
		}

		self.OpenTooltip = function() {
			if (self.currentTooltipElement) {
				self.currentTooltipElement.jqxTooltip("open");
			}
		}

		self.CloseTooltip = function() {
			if (self.currentTooltipElement) {
				self.currentTooltipElement.jqxTooltip("close");
			}
		}

		// contextMenu
		var currentMousePos = { x: -1, y: -1 };
		$(element).mousemove(function(event) {
			currentMousePos.x = event.pageX;
			currentMousePos.y = event.pageY;
		});

		$(element).on("contextmenu", function(e) {
			if (elementWithContextMenuOpen) {
				elementWithContextMenuOpen.closeMenuClick();
			}

			self.openMenuClick(null, null, currentMousePos.x, currentMousePos.y, true);
			self.forbidMainClick = false;
			self.forbidClosingMenu = false;
			return false;
		});

		$buttonComp.on("click", function() {
			if (self.forbidMainClick) {
				self.forbidMainClick = false;
			} else {
				self.realMainClick(currentMousePos.x, currentMousePos.y);
				self.CloseTooltip();
				params.baseModel.onTriggerAction("TriggerClick", []);
			}
		});

		self.openMenuClick = function(data, event, x, y, dontAnimateArrow) {
			if (self.menuEntries().length == 0)
				return;

			self.forbidMainClick = true;
			if (self.menuIsOpen)
				return;
			self.DestroyTooltip();
			elementWithContextMenuOpen = self;

			self.forbidClosingMenu = true;
			self.menuIsOpen = true;
			$menu.stop();

			var x = x || $(element).offset().left + $(element).width() - $menu.outerWidth(true);
			var y = y || $(element).offset().top + $(element).height();

			$menu.detach().appendTo("body");
			$menu.css({
				"position"         : "absolute",
				"left"             : x + "px",
				"top"              : y + "px",
				"background-color" : "#414141",
				"display"          : "block",
				"height"           : "auto",
			});
			var menuHeight = $menu.height();

			$menu.css("height", "0px");
			$menu.animate({"height" : menuHeight}, self.openAnimationDuration);

			var animateArrow = !dontAnimateArrow;
			if (animateArrow) {
				$({deg: 0}).animate({deg: 180}, {
					duration: self.openAnimationDuration,
					step: function(now) {
						$openMenuButton.css({
							transform: 'rotate(' + now + 'deg)',
						});
					},
				});
			} else {
				$openMenuButton.hide();
			}
			self.arrowAnimated = animateArrow;
		}

		self.closeMenuClick = function() {
			if (!self.menuIsOpen)
				return;
			self.CreateTooltip($(element), self.tooltip, self.tooltipShowDelay);
			elementWithContextMenuOpen = null;
			self.menuIsOpen = false;
			$menu.stop();

			$menu.animate({"height": "0px"}, self.openAnimationDuration, function() {
				$menu.css({
					"display" : "none",
					"position": "relative",
					"top"     : "0px",
					"left"    : "0px",
				});
				$menu.detach().appendTo(element);
			});

			if (self.arrowAnimated) {
				$({deg: 180}).animate({deg: 360}, {
					duration: self.openAnimationDuration,
					step: function(now) {
						$openMenuButton.css({
							transform: 'rotate(' + now + 'deg)',
						});
					},
				});
			} else {
				$openMenuButton.show();
			}
		}

		$(window).on("click", function() {
			if (!self.forbidClosingMenu) {
				self.closeMenuClick();
			} else {
				self.forbidClosingMenu = false;
			}
		});

		self.openMenuButtonMouseEnter = function() {
			$openMenuButton.css("opacity", 1.0);
		}

		self.openMenuButtonMouseLeave = function() {
			$openMenuButton.css("opacity", 0.4);
		}
		self.openMenuButtonMouseLeave();

		// desactivate selection
		var desactivateSelectionFunction = function() {
			if (typeof this.onselectstart != 'undefined') {
				this.onselectstart = function() { return false; };
			} else if (typeof this.style.MozUserSelect != 'undefined') {
				this.style.MozUserSelect = 'none';
			} else {
				this.onmousedown = function() { return false; };
			}
		}
		$(element).each(desactivateSelectionFunction);

		// hover colors (load, not load)
		self.mouseEnter = function(data, event) {
			self.backColor(self.hoverBackgroundColor);
		}

		self.mouseLeave = function(data, event) {
			self.backColor(self.backgroundColor);
			self.CloseTooltip();
		}

		// tooltip on text
		self.mouseEnterTitle = function(data, event) {
			if (self.nameWithoutEllipsis != self.name()) {
				self.DestroyTooltip();
				self.CreateTooltip($text, self.nameWithoutEllipsis, 250);
			}
		}

		self.mouseLeaveTitle = function(data, event) {
			if (self.nameWithoutEllipsis != self.name()) {
				self.DestroyTooltip();
				self.CreateTooltip($(element), self.tooltip, 250);
			}
		}

		params.baseModel.resizeFunctions[params.baseModel.resizeFunctions.length] = function(height,width) {
			self.closeMenuClick();
		};

		self.base.initialize();
	}

	return {
		createViewModel: function(params, componentInfo) {
			return new ButtonWithMenuComponentViewModel(params, componentInfo.element);
		}
	};

});

