define(['scripts/knockout-3.3.0', 'scripts/ACTUtils'], function(ko, ACTUtils) {
	return function PropertyUtils() {
		this.Init = function(component, params, element) {
			params.element = element;
			params.visible = ko.observable(params.IsVisible);
			params.active = ko.observable(params.IsActive);
			params.stateMsg = ko.observable(params.StateMessage);
			params.value = ko.observable(params.DisplayValue);
			params.help = ko.observable(params.Help);
			params.buttons = ko.observableArray(params.Buttons);
			params.enable = ko.observable(params.Enable);

			// don't want the label to take unecessary space
			var $propertyLine = $(params.element).children(".propertyLine");
			var $label = $propertyLine.children(".label");
			if (ACTUtils.StringIsNullOrEmpty(params.Caption))
				$label.hide();

			if (params.Attributes && params.Attributes["htmlclasses"]) {
				var classes = params.Attributes["htmlclasses"].split(",");
				for (var i = 0; i < classes.length; i++)
					$(params.element).addClass(classes[i]);
			}

			var floatDisplayValue = null;
			if (params.DisplayValue)
				floatDisplayValue = parseFloat(params.DisplayValue.replace(',','.'))
			params.sliderValue = ko.observable(floatDisplayValue);

			params.updateStateMessageColor = function(stateMessageType) {
				var $stateMessage = $(element).find(".message");
				$stateMessage.removeClass("information warning error")
				var stateMessageToLower = stateMessageType.toLowerCase();
				$stateMessage.addClass(stateMessageToLower);
			}
			params.updateStateMessageColor(params.StateMessageType);

			params.triggerValueChange = function(value) {
				var $input = $(element).find("input");
				if ($input.attr("type") == "checkbox") {
					params.value(value); // cheating but no way to make it constitently work in others ways
				} else {
					$input.val(value).change();
				}
			}

			params.triggerButtonClick = function(buttonName) {
				var selector = "button";
				if (buttonName != "")
					selector += "." + buttonName;

				$button = $(element).find(selector);
				$button.click();
			}

			// not directly on button but on .buttons cause they don't exist yet
			$(element).find(".buttons").on("click", function(event) {
				var buttonName = $(event.toElement).attr("class")
				if (!buttonName) buttonName = "";
				var parentKoComp = ko.contextFor(element).$parent;
				parentKoComp.parent.params.baseModel.onTriggerAction("TriggerButtonClick", [params.Name, buttonName]);
			});

			var $help = $(params.element).find(".help");
			if ($help.length > 0) {
				if (ACTUtils.StringIsNullOrEmpty(params.Help)) {
					$help.hide();
				} else {
					ACTUtils.CreateTooltip($help, params.Help, false, {});
					$help.show();
				}
			}

			params.buttonClick = function(s, a) {
				this.onclick(s);
			}.bind(params)

			$(element).on("contextmenu", function(e) {
				if (params.onrightclick)
					params.onrightclick();
				return false;
			});

			params.value.subscribe(function(newVal) {
				if (!params.updating) {
					var parentKoComp = ko.contextFor(element).$parent;
					parentKoComp.parent.params.baseModel.onTriggerAction("TriggerValueChange", [params.Name, newVal]);

					if (this.Component == "property-radio") {
						var $inputs = $(element).find("form input");
						for (var i = 0; i < $inputs.length; i++) {
							if ($($inputs[i]).val() == newVal) {
								this.onchange(i, true);
								break;
							}
						}
					} else {
						if (params.beforeChange)
							params.beforeChange(newVal);
						this.onchange(newVal);
					}
				}
			}.bind(params));
			return params;
		};

		this.Ready = function(params) {
			params.ready(true);
		};
	};
});
