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

	function ButtonComponentViewModel(params, element) {
		var self = this;
		self.base = new ACTComponent($(element), params);

		self.image = ko.observable();
		self.isDropDown = ko.observable(false);
		self.$element = $(element);
		self.used = false;
		self.disabled = false;
		self.backgroundColor = null;
		self.usedBackgroundColor = null;
		self.textColor = null;
		self.usedTextColor = null;
		self.hovered = false;

		var $buttonDiv = self.$element.find(".buttonDiv");
		var $caption = self.$element.find(".imgAndCaption .caption");
		var $image = self.$element.find(".imgAndCaption img");
		var $dropDown = self.$element.find(".dropDown img");

		self.setDisable = function(d) {
			self.disabled = d;

			if (self.disabled)
				self.$element.addClass("disabled");
			else
				self.$element.removeClass("disabled");
		}

		self.setUsed = function(u) {
			self.used = u;
			// used class
			if (self.used)
				self.$element.addClass("used");
			else
				self.$element.removeClass("used");

			self.updateStyle();
		}

		self.base.onMessage = function(name, obj) {
			if (name == "disabled") {
				self.setDisable(obj);
			} else if (name == "backgroundColor") {
				self.backgroundColor = obj ? obj : "";
				self.updateStyle();
			} else if (name == "usedBackgroundColor") {
				self.usedBackgroundColor = obj ? obj : "";
				self.updateStyle();
			} else if (name == "textColor") {
				self.textColor = obj ? obj : "";
				self.updateStyle();
			} else if (name == "usedTextColor") {
				self.usedTextColor = obj ? obj : "";
				self.updateStyle();
			} else if (name == "used") {
				self.setUsed(obj);
			}
		}

		self.base.onRefresh = function(obj) {
			self.webobject = obj;
			var $element = self.$element;
			if (obj.TriggerClick) {
				$element.trigger("click");
				return;
			} else if (obj.TriggerRightClick) {
				$(element).triggerHandler('contextmenu');
				return;
			}

			params.ready(false);

			self.caption = obj.Caption;
			self.image(obj.Image);
			self.Clicked = obj.Clicked;
			self.HoverStateChanged = obj.HoverStateChanged;
			self.RightClicked = obj.RightClicked;
			self.backgroundColor = obj.BackgroundColor ? obj.BackgroundColor : "";
			self.textColor = obj.TextColor ? obj.TextColor : "";
			self.usedBackgroundColor = obj.UsedBackgroundColor ? obj.UsedBackgroundColor : "";
			self.usedTextColor = obj.UsedTextColor ? obj.UsedTextColor : self.textColor;
			self.allowTextBreak = obj.AllowTextBreak;
			self.fixSize = obj.FixSize;
			self.isDropDown(obj.IsDropDown);

			self.setDisable(obj.Disabled);

			self.setUsed(obj.Used);

			// before computing the width
			if (obj.CaptionSize != -1) {
				$caption.css("font-size", obj.CaptionSize);
			}

			// compute max word width
			var maxWordWidth = 0;
			if (obj.AllowTextBreak) {
				var captions = obj.Caption.split(" ");
				$caption.css({position:"absolute", width:"auto"});
				for (var i = 0; i < captions.length; i++) {
					$caption.text(captions[i]);
					maxWordWidth = Math.max($caption.width(), maxWordWidth);
				}
				$caption.css({position:"", width:""});
				$caption.text(obj.Caption);
				$caption.css("white-space", "");
			} else {
				$caption.text(obj.Caption);
				$caption.css("white-space", "pre");
				$caption.css({position:"absolute", width:"auto"});
				maxWordWidth = $caption.width();
				$caption.css({position:"", width:""});
			}

			if (obj.ImageWidth && obj.ImageWidth != -1) {
				$image.css("width", obj.ImageWidth);
				var newButtonWidth = obj.ImageWidth + 10;
				if ($buttonDiv.width < newButtonWidth) {
					$buttonDiv.css("width", newButtonWidth);
				}
			}
			if (obj.ImageHeight && obj.ImageHeight != -1) {
				$image.css("height", obj.ImageHeight);
			}

			if (obj.TotalWidth && obj.TotalWidth != -1) {
				$buttonDiv.css("width", obj.TotalWidth);
			}
			if (obj.TotalHeight && obj.TotalHeight != -1) {
				$buttonDiv.css("height", obj.TotalHeight);
			}

			if (!obj.FixSize) {
				if (maxWordWidth > $buttonDiv.width() || obj.FitWidthToText) {
					$buttonDiv.css("width", maxWordWidth);
				}
				if ($caption.height() > $buttonDiv.height()) {
					$buttonDiv.css("height", $caption.height());
				}
			}

			self.updateStyle();

			self.base.addCallbackX(self, "clicked", "Clicked");
			self.base.addCallbackX(self, "hoverStateChanged", "HoverStateChanged");
			self.base.addCallbackX(self, "rightClicked", "RightClicked");
			params.ready(true);
		}.bind(self);

		self.updateStyle = function() {
			if (self.used || (self.hovered && !self.disabled)) {
				$buttonDiv.css("background-color", self.usedBackgroundColor);
				$caption.css("color", self.usedTextColor);
			} else {
				$buttonDiv.css("background-color", self.backgroundColor);
				$caption.css("color", self.textColor);
			}
		}

		self.$element.on("mouseenter", function(e) {
			if (self.hovered)
				return false;

			// hovered ~ used
			if (!self.used)
				self.$element.addClass("used");

			self.hovered = true;
			self.updateStyle();
			self.hoverStateChanged(true);
		});

		self.$element.on("mouseleave", function(e) {
			var mx = ACTUtils.GetMousePosition().x;
			var my = ACTUtils.GetMousePosition().y;
			/*
			 * We do that cause if we want to add element like other buttons in our button
			 * the only way is to do a panel with a button and some other manually positioned.
			 * When we do that we don't want to lost the hover state by overing an element that is in the button.
			 * So when we leave but the mouse is still in the box of the button we don't change the hover state.
			 */
			if (ACTUtils.PositionIsInElement(self.$element, mx, my)) {
				// cause the mouseleave event will no longer be called and we want to leave when we leave the element
				setTimeout(function() { self.$element.trigger("mouseleave")}, 10);
				return false;
			}

			// hovered ~ used if not already used by something else (self.used only update by the webobj)
			if (!self.used)
				self.$element.removeClass("used");

			self.hovered = false;
			self.updateStyle();
			self.hoverStateChanged(false);
		});

		self.$element.on("click", function() {
			if (self.disabled)
				return;
			params.baseModel.onTriggerAction("TriggerClick", []);
			var e = self.$element;
			var offset = e.offset();
			self.clicked(offset.left, offset.top, e.outerWidth(), e.outerHeight());
		}.bind(self));

		self.$element.on("contextmenu", function(e) {
			if (self.disabled)
				return;
			params.baseModel.onTriggerAction("TriggerRightClick", []);
			var e = self.$element;
			var offset = e.offset();
			self.rightClicked(offset.left, offset.top, e.outerWidth(), e.outerHeight());
			return false;
		});

		self.updateVerticalAlignment = function() {
			var $imgAndCaption = self.$element.find(".imgAndCaption");
			if (!$imgAndCaption.is(":visible"))
				return;
			$imgAndCaption.css("margin-top", (self.$element.height() - $imgAndCaption.height()) * 0.5);
		}

		self.onResize = function() {
			if (self.fixSize)
				ACTUtils.ApplyEllipsis($caption, self.caption, ($buttonDiv.height() - $image.height()));
			self.updateVerticalAlignment();
		}

		params.baseModel.resizeFunctions.push(self.onResize);
		params.baseModel.showFunctions.push(self.onResize);

		params.baseModel.updateCSSFunctions.push(function(cssProperty) {
			if (cssProperty.Name === "font-weight")
				self.base.onRefresh(self.webobject);
		});

		self.base.initialize();
	}

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