/* 
	- Implements optgroup
	- Implements remove Option
	- Implements parse html select
	-Fix selected for IE
	-Implements disabled select
*/


function getOffsetElement(element)
{
	var top = left = 0;
	while(element)
	{
		top += element.offsetTop;
		left += element.offsetLeft;
		element = element.offsetParent;
	}
	
	var offset = [left, top];
	return offset;
}

function OptionItem(properties)
{
	var option = document.createElement('option');
	for (var i in properties)
	{
		option[i] = properties[i];
	}
	
	return option;
}

var ComboBox = function()
{
	var instance = false;
	var instance_coll = [];
	
	function ComboBox(properties, html_select)
	{
		var img_combo = properties.src || 'images/combo_box.gif'; 
		
		var custom_combo_box = document.createElement('div');
			custom_combo_box.className = properties.className || 'combo_box';
			if (properties.width) custom_combo_box.style.width = properties.width + 'px';
			if (properties.height) custom_combo_box.style.height = properties.height + 'px';
			custom_combo_box.innerHTML = '<img src="' + img_combo + '" alt="" style="float: right; height: 100%" /><label></label>';
			
		var combo_box = html_select || document.createElement('select');
			combo_box.className = 'hidden_component';
			if (properties.name) combo_box.name = properties.name;
			if (properties.id) combo_box.id = properties.id;
			if (properties.onChange) combo_box.onchange_listener = properties.onChange;
			
			combo_box.custom_combo_box = custom_combo_box;
			custom_combo_box.select = combo_box;
		var curr_parent = combo_box;
		
		this.addOption = function(OptionItem)
		{
			if (window.addEventListener)
			{
				curr_parent.appendChild(OptionItem);
				return;
			}
			combo_box.add(OptionItem);
		}
		
		/*this.addOptgroup = function(label_text)
		{
			curr_parent = document.createElement('optgroup');
			curr_parent.label = label_text || '';
			combo_box.appendChild(curr_parent);
		}*/
		
		this.flushOptions = function()
		{
			combo_box.options.length = 0;
		}
		
		this.renderComboBox = function(parentCombo)
		{
			var parent_combobox = document.getElementById(parentCombo) || parentCombo;
			ComboBox.setUpdateText.call(combo_box, null, true);
			
			if (combo_box.addEventListener)
			{
				combo_box.addEventListener('keyup', combo_box.blur, false);
				combo_box.addEventListener('keyup', combo_box.focus, false);
			}
			
			Event.addEvent(combo_box, 'change', ObserverDropDown.moveKeySelected, false);
			Event.addEvent(combo_box, 'change', ComboBox.setUpdateText, false);
			Event.addEvent(combo_box, 'keydown', ObserverDropDown.checkKey, false);
			Event.addEvent(combo_box, 'focus', ComboBox.focus, false);
			Event.addEvent(combo_box, 'blur', ComboBox.blur, false);
			
			if (!html_select) parent_combobox.appendChild(combo_box);
			
			Event.addEvent(custom_combo_box, 'click', ObserverDropDown.showDropDown, false);
			
			parent_combobox.insertBefore(custom_combo_box, combo_box);
		}
		
		if (!instance)
		{
			if (document.body)
			{
				ObserverDropDown.initDropDown();
			}
			else 
			{
				Event.addEvent(window, 'load', ObserverDropDown.initDropDown, false);
			}
			
			instance = true;
		}
		
		if (!window.XMLHttpRequest)
		{
			instance_coll[instance_coll.length] = custom_combo_box;
		}
	}
	
	/*Prevent memory leak in IE6*/
	if (!window.XMLHttpRequest)
	{
		window.attachEvent('onunload', function()
		{
			for (var i = 0, len = instance_coll.length; i < len; i++)
			{
				instance_coll[i].select.custom_combo_box = null;
				instance_coll[i].select = null;
			}
		});
	}
	
	return ComboBox;
}();

ComboBox.setUpdateText = function(event, onchange_flag)
{
	if (this.selectedIndex >= 0)
	{
		this.custom_combo_box.getElementsByTagName('label')[0].innerHTML = this.options[this.selectedIndex].text;
		if (!onchange_flag && this.onchange_listener instanceof Function)
		{
			this.onchange_listener(this);
		}
	}
}

ComboBox.setSelectedIndex = function(index)
{
	if (index >= 0)
	{
		this.selectedIndex = index;
		ComboBox.setUpdateText.call(this);
	}
}

ComboBox.focus = function()
{
	this.custom_combo_box.getElementsByTagName('label')[0].className = 'combo_box_focus'
}

ComboBox.blur = function()
{
	this.custom_combo_box.getElementsByTagName('label')[0].className = '';
}

var ObserverDropDown = function()
{
	function ObserverDropDown()
	{
		var drop_down_id = 'drop_down_combo_box';
		var selected_class_name = 'selected_index';
		
		var drop_down = null;
		var curr_combo_box = null;
		var default_selected_index = null;
		var old_selected_index = null;
		var self = this;
		
		this.initDropDown = function()
		{
			drop_down = document.createElement('div');
				drop_down.id = drop_down_id;
			var drop_down_style = drop_down.style;
				drop_down_style.position = 'absolute';
				drop_down_style.zIndex = '100000';
				drop_down_style.display = 'none';
				
				Event.addEvent(drop_down, 'scroll', self.focusSelect, false);
				
			document.body.appendChild(drop_down);
		}
		
		this.showDropDown = function(event)
		{
			this.select.focus();
			if (this != curr_combo_box)
			{
				curr_combo_box = this;
				default_selected_index = old_selected_index = curr_combo_box.select.selectedIndex;
				positionResizeDropDown();
				renderOptions();
				drop_down.style.display = 'block';
				drop_down.scrollTop = getSelectedOffset();
				Event.stopPropagation(event);
				
				Event.addEvent(document, 'click', self.hideDropDown, false);
				Event.addEvent(window, 'resize', self.hideDropDown, false);
			}
		}
		
		this.hideDropDown = function(event) 
		{
			drop_down.style.display = 'none';
			if (curr_combo_box.select.selectedIndex != default_selected_index)
			{
				curr_combo_box.select.selectedIndex = default_selected_index;
			}
			curr_combo_box.select.focus();
			curr_combo_box = null;
			Event.removeEvent(document, 'click', self.hideDropDown, false);
			Event.removeEvent(window, 'resize', self.hideDropDown, false);
		}
		
		this.moveSelected = function(index)
		{
			if (index != old_selected_index)
			{
				var obj = drop_down.getElementsByTagName('label');
				obj[old_selected_index].className = '';
				obj[index].className = selected_class_name;
				curr_combo_box.select.selectedIndex = old_selected_index = index;
			}
		}
		
		this.moveKeySelected = function()
		{
			if (curr_combo_box)
			{
				default_selected_index = curr_combo_box.select.selectedIndex;
				self.moveSelected(default_selected_index);
				drop_down.scrollTop = getSelectedOffset();
			}
		}
		
		this.setSelectedIndex = function(index)
		{
			default_selected_index = index;
			ComboBox.setSelectedIndex.call(curr_combo_box.select, index);
		}
		
		this.checkKey = function(event)
		{
			var code = event.keyCode; 
			if (curr_combo_box && (code == 9 || code == 13))
			{
				self.hideDropDown();
			}
		}
		
		this.focusSelect = function()
		{
			curr_combo_box.select.focus();
		}
		
		function positionResizeDropDown()
		{
			var pos = getOffsetElement(curr_combo_box);
			drop_down.style.left = pos[0] + 'px';
			drop_down.style.top = pos[1] + curr_combo_box.offsetHeight + 'px';
			drop_down.style.width = curr_combo_box.clientWidth + 'px';
		}
		
		function getSelectedOffset()
		{
			if (default_selected_index > -1)
			{
				var obj = drop_down.getElementsByTagName('label')[curr_combo_box.select.selectedIndex];
				var scroll = drop_down.scrollTop;
				var obj_top = obj.offsetTop;
				var obj_height = obj.offsetHeight + 2;
				
				if (obj_top < scroll)
				{
					return obj_top;
				}
				
				if (obj_top > scroll + drop_down.offsetHeight - obj_height)
				{
					return obj_top - (drop_down.offsetHeight - obj_height);
				}
				return scroll;
			}
		}
		
		function renderOptions()
		{
			var index = -1;
			function replaceOption(match)
			{
				index++;
				
				return '<label onmouse' + (window.ActiveXObject ? 'over' : 'move') + '=ObserverDropDown.moveSelected(' + index + ') onclick=ObserverDropDown.setSelectedIndex(' + index + ')>'; 
			}
			
			var html_code = curr_combo_box.select.innerHTML;
			html_code = html_code.replace(/<option[^>]+>/ig, replaceOption);
			html_code = html_code.replace(/<\/option/ig, '</label');
			drop_down.innerHTML = html_code;
			if (index > -1)
			{
				drop_down.getElementsByTagName('label')[curr_combo_box.select.selectedIndex].className = selected_class_name;
			}
			
		}
		
	}

	return new ObserverDropDown();
}();