/* namespace nx.combobox { */
nx.combobox = new Object();

nx.combobox.Option = Class.create();
nx.combobox.Option.prototype = {
	parentNode: false,
	optionIndex: -1,
	
	initialize: function(parentNode, optionIndex, optionValue, optionText) {
		this.parentNode  = parentNode;
		this.optionIndex = optionIndex;
		this.optionNode  = new Element("div", {
			//"className": "nx_combobox_Option nx_combobox_OptionStyle"
		});
		this.optionNode.addClassName("nx_combobox_Option");
		this.optionNode.addClassName("nx_combobox_OptionStyle");
		
		this.setValue(optionValue);
		this.setText(optionText);
		
		Event.observe(this.optionNode, 'click', function(event) {
			$A(arguments)[1].parentNode.optionSelected($A(arguments)[1].optionIndex);
		}.bindAsEventListener(this.optionNode, this));
	
		Event.observe(this.optionNode, 'mouseover', function(event) {
			this.addClassName("nx_combobox_OptionHovered");
			this.addClassName("nx_combobox_OptionHoveredStyle");
		}.bindAsEventListener(this.optionNode));
		
		Event.observe(this.optionNode, 'mouseout', function(event) {
			this.removeClassName("nx_combobox_OptionHovered");
			this.removeClassName("nx_combobox_OptionHoveredStyle");
		}.bindAsEventListener(this.optionNode));
	},
	
	getValue: function() {
		return this.optionValue;
	},
	
	setValue: function(value) {
		this.optionValue = value;
	},
	
	getText: function() {
		return this.optionText;
	},
	
	setText: function(value) {
		this.optionText = value;
		this.optionNode.innerHTML = value;
	}
};

nx.combobox.Button = Class.create();
nx.combobox.Button.prototype = {
	hasFocus: false,
	parentNode: null,
	buttonNode: null,
	
	initialize: function(parentNode) {
		this.parentNode = parentNode;
		this.buttonNode = new Element("span", {
			//"className": "nx_combobox_Button nx_combobox_ButtonStyle"
		});
		this.buttonNode.addClassName("nx_combobox_Button");
		this.buttonNode.addClassName("nx_combobox_ButtonStyle");
		this.buttonNode.update("&gt;");
		
		Event.observe(this.buttonNode, 'click', function(event) {
			$A(arguments)[1].parentNode.toggleOptions();
		}.bindAsEventListener(this.buttonNode, this));
	
		Event.observe(this.buttonNode, 'mouseover', function(event) {
			if ($A(arguments)[1].hasFocus)
				return;
			
			this.addClassName("nx_combobox_ButtonHovered");
			this.addClassName("nx_combobox_ButtonHoveredStyle")
		}.bindAsEventListener(this.buttonNode, this));
		
		Event.observe(this.buttonNode, 'mouseout', function(event) {
			if ($A(arguments)[1].hasFocus)
				return;
			
			this.removeClassName("nx_combobox_ButtonHovered");
			this.removeClassName("nx_combobox_ButtonHoveredStyle");
		}.bindAsEventListener(this.buttonNode, this));
	},

	setFocus: function(focus) {
		if (focus) {
			this.hasFocus = true;
			this.buttonNode.addClassName("nx_combobox_ButtonFocus");
			this.buttonNode.addClassName("nx_combobox_ButtonFocusStyle");
		} else {
			this.hasFocus = false;
			this.buttonNode.removeClassName("nx_combobox_ButtonFocus");
			this.buttonNode.removeClassName("nx_combobox_ButtonFocusStyle");
		}
	}
};

nx.combobox.Clearer = Class.create();
nx.combobox.Clearer.prototype = {
	parentNode: null,
	clearerNode: null,
	
	initialize: function(parentNode) {
		this.parentNode  = parentNode;
		this.clearerNode = new Element("span", {
			//"className": "nx_combobox_Clearer"
		});
		this.clearerNode.addClassName("nx_combobox_Clearer");
	}
};

nx.combobox.Combobox = Class.create();
nx.combobox.Combobox.prototype = {
	initialize: function() {
	},
	
	init: function() {
		this.addClassName("nx_combobox_ComboboxStyle");
		
		this.sourceNode = this.select("select")[0];
		this.sourceNode.hide();
	
		this.wrapperNode = new Element("span", {
			"className": "nx_combobox_Wrapper"
		});
	
		this.controlNode = new Element("span", {
			//"className": "nx_combobox_Control nx_combobox_ControlStyle"
		});
		this.controlNode.addClassName("nx_combobox_Control");
		this.controlNode.addClassName("nx_combobox_ControlStyle");
	
		this.optionsNode = new Element("span", {
			"className": "nx_combobox_ComboboxOptions nx_combobox_ComboboxOptionsStyle",
			"style": "display: none; position: absolute; z-index: 7;"
		});
		this.optionsNode.addClassName("nx_combobox_ComboboxOptions");
		this.optionsNode.addClassName("nx_combobox_ComboboxOptionsStyle");		

		this.optionNodes = new Array();
		for (var optionIndex = 0; optionIndex < this.sourceNode.options.length; optionIndex ++) {
			var optionNode = new nx.combobox.Option(this, optionIndex,
				this.sourceNode.options[optionIndex].value,
				this.sourceNode.options[optionIndex].innerHTML
			);
			
			this.optionNodes[optionIndex] = optionNode;
			this.optionsNode.appendChild(optionNode.optionNode);
		}
		
		this.controlOption = new nx.combobox.Option(this, -1,
			this.sourceNode.options[this.sourceNode.selectedIndex].value,
			this.sourceNode.options[this.sourceNode.selectedIndex].innerHTML
		);
		
		Event.observe(this.controlOption.optionNode, 'click', function(event) {
			$A(arguments)[1].parentNode.toggleOptions();
		}.bindAsEventListener(this.controlOption.optionNode, this.controlOption));
		
		this.controlButton  = new nx.combobox.Button(this);
		this.controlClearer = new nx.combobox.Clearer(this);
	
		this.controlNode.appendChild(this.controlOption.optionNode);
		this.controlNode.appendChild(this.controlButton.buttonNode);
		this.controlNode.appendChild(this.controlClearer.clearerNode);
	
		this.wrapperNode.appendChild(this.controlNode);
		this.wrapperNode.appendChild(this.optionsNode);
	
		this.appendChild(this.wrapperNode);
		
		this.periodicalExecuter = new PeriodicalExecuter(function(periodicalExecuter) {
			if (!this.oldSelectedIndex)
				this.oldSelectedIndex = this.observedObject.sourceNode.selectedIndex;
			
			if (this.oldSelectedIndex != this.observedObject.sourceNode.selectedIndex) {
				this.observedObject.controlOption.setValue(this.observedObject.optionNodes[this.observedObject.sourceNode.selectedIndex].getValue());
				this.observedObject.controlOption.setText(this.observedObject.optionNodes[this.observedObject.sourceNode.selectedIndex].getText());
	
				this.oldSelectedIndex = this.observedObject.sourceNode.selectedIndex;
			}
		}, 0.2);
		this.periodicalExecuter.observedObject = this;
	},
	
	toggleOptions: function() {
		if (this.optionsNode.visible())
			this.hideOptions();
		else
			this.showOptions();
	},

	showOptions: function() {
		var allComboboxes = $$("span.nx_combobox_Combobox select");
		for (var i = 0; i < allComboboxes.size(); i ++) {
			if (allComboboxes[i].parentNode == this)
				continue;
			
			allComboboxes[i].parentNode.hideOptions();
		}

		this.controlButton.setFocus(true);
		this.optionsNode.show();
	},
	
	hideOptions: function() {
		this.controlButton.setFocus(false);
		this.optionsNode.hide();
	},
	
	optionSelected: function(optionIndex) {
		if (optionIndex < 0 || optionIndex >= this.sourceNode.options.length)
			return;
		
		this.controlOption.setValue(this.optionNodes[optionIndex].getValue());
		this.controlOption.setText(this.optionNodes[optionIndex].getText());

		if (this.sourceNode.selectedIndex != optionIndex) {
			this.sourceNode.selectedIndex = optionIndex;
			if (this.sourceNode.onchange)
				this.sourceNode.onchange();
		}
		
		this.hideOptions();
	}
};

Event.observe(window, 'load', function(event) {
	peridodicalExecuter = new PeriodicalExecuter(function(periodicalExecuter) {
		var allComboboxes = $$("span.nx_combobox_Combobox select");
		for (var i = 0; i < allComboboxes.size(); i ++) {
			if ($(allComboboxes[i].parentNode).init) {
				continue;
			}
			
			Object.extend($(allComboboxes[i].parentNode), new nx.combobox.Combobox()).init();
		}
	}, 0.5);

	Event.observe(document, 'click', function(event) {
		if (!event.element() || !event.element().className
				|| !event.element().className.match(/\bnx_combobox.*\b/)) {
			var allComboboxes = $$("span.nx_combobox_Combobox select");
			for (var i = 0; i < allComboboxes.size(); i ++) {
				allComboboxes[i].parentNode.hideOptions();
			}
		}
	}.bindAsEventListener(document));
}.bindAsEventListener(window));
/* } */

