if (!window.Richfaces) window.Richfaces = {};
Richfaces.ComboBox = Class.create();


Richfaces.ComboBox.prototype = {
	
	initialize: function(combobox, listId, parentListId, valueFieldId, fieldId, buttonId, buttonBGId, shadowId, classes, 
						 listWidth, listHeight, itemsText, directInputSuggestions, filterNewValue, 
						 selectFirstOnUpdate, onlistcall, onselected, defaultMessage, isDisabled, value,
						 showDelay, hideDelay) {
		
		this.directInputSuggestions = directInputSuggestions;
		this.filterNewValue = filterNewValue;
		
		this.combobox = $(combobox); 
		this.comboValue = $(valueFieldId);
		this.field = $(fieldId);
		this.BUTTON_WIDTH = 17; //px
		
		//this.field.prevValue = null;
		
		this.button = $(buttonId);
		this.buttonBG = $(buttonBGId);
		
		this.setInputWidth();
		
//		var fieldDem = Richfaces.ComboBoxList.getElemXY(this.field);
//		fieldDem.height = this.field.offsetHeight;
		listWidth = (!listWidth) ? this.getCurrentWidth() : listWidth;
		
		this.comboList = new Richfaces.ComboBoxList(listId, parentListId, selectFirstOnUpdate, classes.COMBO_LIST, listWidth, 
													listHeight, itemsText, onlistcall, fieldId, shadowId, showDelay, hideDelay);
		this.defaultMessage = defaultMessage;
		if (value) {
			var item = this.comboList.findItemBySubstr(value);
			if (item) {
				this.comboList.doSelectItem(item);
			}
		} else {
			if (this.defaultMessage) {
				this.applyDefaultText();
			}
		}
		this.onselected = onselected;
		this.isSelection = true;
		this.classes = classes;
		this.isDisabled = isDisabled;
		if (this.onselected) {
			this.combobox.observe("rich:onselect", this.onselected);
		}
		if (this.isDisabled) {
			this.doDisable();
		}
		
		if (Richfaces.browser.isIE6) {
			this.comboList.createIframe(this.combobox, listWidth, this.combobox.id, 
										"rich-combobox-list-width rich-combobox-list-scroll rich-combobox-list-position");
		}
		this.combobox.component = this;
		this.initHandlers();
	},
	
	initHandlers : function() {
		this.button.observe("click", function(e){this.buttonClickHandler(e);}.bindAsEventListener(this));
		this.button.observe("mouseup", function(e){this.buttonMouseUpHandler(e);}.bindAsEventListener(this));
		this.button.observe("mousedown", function(e){this.buttonMousedownHandler(e);}.bindAsEventListener(this));
		this.button.observe("mouseover", function(e){this.buttonMouseOverHandler(e);}.bindAsEventListener(this));
		this.button.observe("mouseout", function(e){this.buttonMouseOutHandler(e);}.bindAsEventListener(this));
		
		this.field.observe("keydown", function(e){this.fieldKeyDownHandler(e);}.bindAsEventListener(this));
		this.field.observe("blur", function(e){this.fieldBlurHandler(e);}.bindAsEventListener(this));
		this.field.observe("focus", function(e){this.fieldFocusHandler(e);}.bindAsEventListener(this));
		this.field.observe("keyup", function(e){this.dataUpdating(e);}.bindAsEventListener(this));
		
		this.comboList.listParent.observe("mousedown", function(e){this.listMousedownHandler(e);}.bindAsEventListener(this));
		this.comboList.listParent.observe("mousemove", function(e){this.listMouseMoveHandler(e)}.bindAsEventListener(this));
		this.comboList.listParent.observe("click", function(e){this.listClickHandler(e);}.bindAsEventListener(this));
	},
	
	setInputWidth : function() {
		var width = (parseInt(this.field.parentNode.style.width) - this.BUTTON_WIDTH) + Richfaces.getBorderWidth(this.field, "r");
		if (Prototype.Browser.Gecko) {
			//border width and padding width not included in the general component width
			width -= Richfaces.getPaddingWidth(this.field, "lr") 
					 + Richfaces.getPaddingWidth(this.button, "lr") 
					 + Richfaces.getBorderWidth(this.field, "lr") 
					 + Richfaces.getBorderWidth(this.button, "lr");
		}
		this.field.style.width = width + "px"; 	
	},
	
	buttonClickHandler : function(event) {
		if (this.comboList.visible()) {
			this.comboList.hideWithDelay();
		} else {
			this.comboList.createDefaultList();
			this.comboList.showWithDelay();
			if (this.comboList.selectedItem) {
				this.comboList.scrollingUpToItem(this.comboList.selectedItem);
			}
			this.comboList.isList = false;
		}
	},
	
	buttonMouseUpHandler : function(e) {
		this.buttonBG.className = "rich-combobox-font rich-combobox-button-background rich-combobox-button";
		this.button.className = this.classes.BUTTON.CLASSES.ACTIVE + " rich-combobox-button-hovered";
		this.field.focus();	
	},
	
	buttonMousedownHandler : function(e) {
		this.buttonBG.className = "rich-combobox-font rich-combobox-button-pressed-background rich-combobox-button";
		this.button.className = this.classes.BUTTON.CLASSES.ACTIVE + " rich-combobox-button-hovered";
		this.comboList.isList = true;
	},
	
	buttonMouseOverHandler : function(e) {
		var classCss = this.classes.BUTTON.CLASSES;
		var iconStyles = this.classes.BUTTONICON.STYLE;
		
		if (this.isActive()) { 
			this.button.className= classCss.ACTIVE + " " + classCss.HOVERED;
			this.button.style.backgroundImage = iconStyles.ACTIVE;			
		} else {
			this.button.className = classCss.NORMAL + " " + classCss.HOVERED;
			this.button.style.backgroundImage = iconStyles.NORMAL; 
		}
	},
	
	buttonMouseOutHandler : function(e) {
		var classCss = this.classes.BUTTON.CLASSES;
		var iconStyles = this.classes.BUTTONICON.STYLE;
		
		if (this.isActive()) { 
			this.button.className= classCss.ACTIVE;
			this.button.style.backgroundImage = iconStyles.ACTIVE;
		} else {
			this.button.className = classCss.NORMAL;
			this.button.style.backgroundImage = iconStyles.NORMAL;
		}
	},
	
	listMouseMoveHandler : function(event) {
		//changes item's decoration
		var item = this.comboList.getEventItem(event);
		if (item) {
			this.comboList.doActiveItem(this.comboList.getEventItem(event));			
		}
	},
	
	listMousedownHandler : function(e) {
		if (Prototype.Browser.IE) {
			if (!this.comboList.getEventItem(e)) {
				this.clickOnScroll = true;
			}
			this.comboList.isList = true;
		} else if (Prototype.Browser.Gecko) {
			if (this.comboList.getEventItem(e)) {
				this.comboList.isList = true;			
			}
		} else {
			this.comboList.isList = true;
		}
	},
	
	listClickHandler : function(event) {
		this.isSelection = false;
		this.field.focus();
		this.setValue(true);
		this.comboList.hideWithDelay();
	},
	
	fieldKeyDownHandler : function(event) {
		switch (event.keyCode) {
			case Event.KEY_RETURN : 
				this.setValue(true);
				this.comboList.hideWithDelay();
				Event.stop(event);
				break;
			case Event.KEY_DOWN : 
				this.comboList.moveActiveItem(event);
				break;
			case Event.KEY_UP :
				this.comboList.moveActiveItem(event);
				break; 
			case Event.KEY_ESC : 
				this.field.value = this.field.value; //field must lose focus
				this.comboList.hideWithDelay();
				break;
		}
	},
	
	fieldFocusHandler : function() {
		this.doActive();
		if ((this.field.value == this.defaultMessage) && (this.comboValue.value == "")) {
			this.field.value = "";
		} else {
			if (this.isSelection) {
				Richfaces.ComboBox.textboxSelect(this.field, 0, this.field.value.length);
			}
			this.isSelection = true;
		}
	},
	
	fieldBlurHandler : function(event) {
		if (!this.comboList.isList) {
			this.doNormal();
			var value = this.field.value; 
			if (value.length == 0) {
				this.applyDefaultText();
			} else {
				var item = this.comboList.findItemBySubstr(value);
				if (item) {
					this.comboList.doSelectItem(item);
				}
			}
			this.comboList.hideWithDelay();
		} else {
			this.doActive();
		}
		
		if (this.clickOnScroll) {
			//after clicking on scroll (IE)
			this.field.focus();
			this.comboList.isList = false;
			this.clickOnScroll = false;
		}
	},
	
	dataUpdating : function(event) {
		if (Richfaces.ComboBox.SPECIAL_KEYS.indexOf(event.keyCode) == -1) {
			if (this.filterNewValue) {
				this.comboList.hideWithDelay();
				this.comboList.dataFilter(this.field.value);
				if (this.comboList.getItems() && this.comboList.getItems().length != 0) {
					var isSearchSuccessful = true;
					this.comboList.showWithDelay();					
				}
			} else {
				if (!this.comboList.visible()) {
					this.comboList.showWithDelay();
				}
				var item = this.comboList.findItemBySubstr(this.field.value);
				if (item) {
					this.comboList.doActiveItem(item);
					this.comboList.scrollingUpToItem(this.comboList.activeItem);
					isSearchSuccessful = true;
				}
			}
			
			if (this.isValueSet(event) && isSearchSuccessful) {
				this.setValue();
			}
			this.comboValue.value = this.field.value; 
		}
	},
	
	wasTextDeleted : function(event) {
		if ((event.keyCode == Event.KEY_BACKSPACE) 
			|| (event.keyCode == Event.KEY_DELETE) 
			|| (event.ctrlKey && (event.keyCode == 88))) {
			return true;
		}
		return false;
	},
	
	isValueSet : function(event) {
		/*if (this.field.prevValue) {
			if (this.field.prevValue.toLowerCase() != this.field.value.toLowerCase()) {
				return true;
			}
			return false;
		}
		return true;*/
		if (this.wasTextDeleted(event) 
			|| (event.keyCode == 17) 
			|| event.altKey 
			|| event.ctrlKey 
			|| event.shiftKey) {
			return false;
		}
		return true;
	},
	
	setValue : function(toSetOnly) {
		if (!this.comboList.activeItem) {
			return;
		}
		var value = this.comboList.activeItem.innerHTML;
		if (toSetOnly) {
			var oV = this.field.value; 
			if (oV == value) {
				if (Prototype.Browser.Gecko) {
					this.field.value = "";
					this.comboValue.value = "";
				}
			}
			this.field.prevValue = value;
			this.field.value = value;
			this.comboValue.value = value;
			this.comboList.doSelectItem(this.comboList.activeItem);
			this.combobox.fire("rich:onselect", {});
		} else {
			if (this.directInputSuggestions) {
				var startInd = this.field.value.length; 
				var endInd = value.length;
				//this.field.prevValue = this.field.value;
				this.field.value = value;
				Richfaces.ComboBox.textboxSelect(this.field, startInd, endInd);
			} 
		}
	},
	
	applyDefaultText : function() {
		this.field.className = this.classes.FIELD.CLASSES.DISABLED;
		this.field.value = this.defaultMessage;
		this.comboValue.value = "";
	},
	
	isActive : function() {
		return (this.field.className == this.classes.FIELD.CLASSES.ACTIVE); 
	},
	
	doActive : function() {
		if (this.button.className.indexOf(this.classes.BUTTON.CLASSES.HOVERED) != -1) {
			this.button.className = this.classes.BUTTON.CLASSES.ACTIVE + " " + this.classes.BUTTON.CLASSES.HOVERED;
		} else {
			this.button.className = this.classes.BUTTON.CLASSES.ACTIVE ;
		}
		
		var iconStyles = this.classes.BUTTONICON.STYLE;
		this.button.style.backgroundImage = iconStyles.ACTIVE;
		
		this.field.className = this.classes.FIELD.CLASSES.ACTIVE;
 		this.isDisabled = false;
	},
	
	doDisable : function() {
		this.button.className = this.classes.BUTTON.CLASSES.DISABLED;
		this.buttonBG.className = this.classes.BUTTONBG.CLASSES.DISABLED;
		this.field.className = this.classes.FIELD.CLASSES.DISABLED;
		
		var iconStyles = this.classes.BUTTONICON.STYLE;
		this.button.style.backgroundImage = iconStyles.DISABLED;
			
		this.button.disabled = true;
		this.field.disabled = true;
		
		this.isDisabled = true;
	},
	
	doNormal : function() {
		this.button.className = this.classes.BUTTON.CLASSES.NORMAL;
		this.buttonBG.className = this.classes.BUTTONBG.CLASSES.NORMAL;
		this.field.className = this.classes.FIELD.CLASSES.NORMAL;
		
		var iconStyles = this.classes.BUTTONICON.STYLE;
		this.button.style.backgroundImage = iconStyles.NORMAL;
				
		this.button.disabled = false;
		this.field.disabled = false;
		this.isDisabled = false;
	},
	
	getCurrentWidth : function() {
		return this.combobox.firstChild.offsetWidth;	
	},
	
	/**
	 * user's JavaScript API
	 */
	 showList : function() {
	 	this.buttonClickHandler();
	 },
	 
	 hideList : function() {
	 	this.comboList.hideWithDelay();
	 }
};


Richfaces.ComboBox.textboxSelect = function(oTextbox, iStart, iEnd) {
   if (Prototype.Browser.IE) {
       var oRange = oTextbox.createTextRange();
       oRange.moveStart("character", iStart);
       oRange.moveEnd("character", -oTextbox.value.length + iEnd);      
       oRange.select();                                              
   } else if (Prototype.Browser.Gecko) {
       oTextbox.setSelectionRange(iStart, iEnd);
   } else {
   		//FIXME
   		oTextbox.setSelectionRange(iStart, iEnd);
   }                    
} 

Richfaces.ComboBox.getSelectedText = function(oTextbox) {
	if (window.getSelection) {
		return window.getSelection().text;
	} else if (document.selection) { 
		// should come last; Opera!
		return document.selection.createRange();
	} else {
		//TODO
	}
}

Richfaces.ComboBox.SPECIAL_KEYS = [
	Event.KEY_RETURN, Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RIGHT, Event.KEY_LEFT, Event.KEY_ESC
]