define(['scripts/knockout-3.3.0', 'mod/properties/propertyutils', 'jqx/jqxbuttons', 'jqx/jqxdropdownbutton',
	'jqx/jqxmenu'],
function(ko, PropertyUtils) {

    function PropertySelectApplyViewModel(params, element) {
		this.utils = new PropertyUtils();
		this.utils.Init(this, params, element);

		if (params.Caption ==="") {
			$(element).find(".label").css("display", "none");
		}

		var $button = $(element).find(".jqxButton");
		var $ddButton = $(element).find(".jqxDropDownButton");
		var $menu = $(element).find(".jqxMenu");

		var options = params.Options;
		
		// Menu example, "::" indicates a new submenu :
		// [ "Pression", "Temperature", "Velocity", "Velocity::X", "Velocity::Y", "Velocity::Z" ]
		// yields :
		// |- Pression
		// |- Temperature
		// |- Velocity		> |- X
		//    				  |- Y
		//    				  |- Z

		var source = [];
		for (var i = 0; i < options.length; i++) {
			var entry = options[i];
			var splits = entry.split("::");
			if (splits.length === 1) {
				source.push({label:splits[0], value:entry, id:i});
				continue;
			}
			var temp;
			var items = source;
			for (var j = 0; j < splits.length - 1; j++) {
				var split = splits[j];
				if (items === undefined) {
					break;
				}
				for (var k = 0; k < items.length; k++) {
					var obj = items[k];
					if (obj["label"] === split) {
						temp = obj;
						break;
					}
				}
				if (temp !== undefined) {
					items = temp[items];
				}
			}
			if (temp !== undefined) {
				if (temp["items"] === undefined) {
					temp["items"] = [];
				}
				temp["items"].push({label:splits[splits.length - 1], value:entry, id:i});
			}			
		}

		$button.jqxButton({
			height:"23px"
		});		
		$button.text(params.Attributes["buttoncaption"]);
		$ddButton.jqxDropDownButton({ width:'188px', height:'24px', openDelay:50, closeDelay:50});
		$menu.jqxMenu({
			source: source,
			width:'188px',
			mode:'vertical',
			animationShowDelay:50,
			animationHideDelay:50
		});
		$ddButton.jqxDropDownButton('setContent', params.value());

		var selectedIndex = -1;
		$menu.on('itemclick', function(event) {
			$ddButton.jqxDropDownButton('setContent', $(event.target).attr('item-value'));
			$ddButton.jqxDropDownButton('close');
			selectedIndex = parseInt($(event.target).attr('id'), 10);
			// Small hack to prevent any submenu to be opened while the menu is closing.
			// If you hover over an item linked to a submenu the popup will stay on screen while
			// the main menu is closed.
			for (var i = 0; i < options.length; i++) {
				$menu.jqxMenu('disable', "" + i, true);
			}
		});

		$ddButton.on('open', function(event) {
			for (var i = 0; i < options.length; i++) {
				$menu.jqxMenu('disable', "" + i, false);
			}
		});

		$button.on('click', function() {
			params.onchange(selectedIndex, true);
		});	
		
		params.value.subscribe(function(newVal) {
			// If newVal is the same (type and value) as selectedIndex then the event was raised by a click
			// on the button, not by an update on the C# side.
			if (newVal === selectedIndex) {
				return false;
			}
			// Updates the value displayed.
			$ddButton.jqxDropDownButton('setContent', newVal);
			// Look for the index matching the new value in case the user clicks on the button before 
			// selecting another value in the list.
			selectedIndex = -1;
			var currentList = source;
			var current = {};
			var nextList = [];
			var found = false;
			while (!found) {
				if (currentList.length === 0) {
					break;
				}
				nextList = [];
				for (var i = 0; i < currentList.length; i++) {
					current = currentList[i];
					if (current['value'] === newVal) {
						selectedIndex = current['id'];
						found = true;
						break;				
					}
					if (currentList[i]["items"] !== undefined) {
						for (var j = 0; j < current["items"].length; j++) {
							nextList.push(current["items"][j]);
						}
					}
				}
				currentList = nextList;
			}
		});	
		
		this.utils.Ready(params);
		return params;
    }

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