Autocompleter.ComboBox = Class.create(Autocompleter.Base, {
  initialize: function(comboName, autocompleteScript, onChangeScript) {
    this.comboName = comboName;
    this.lastValue = "";
    this.autocompleteScript = autocompleteScript;
    this.onChangeScript = onChangeScript;
    this.baseInitialize(comboName + '_fake', comboName + '_values',{});
    Event.observe(this.element, "click", this.activate.bindAsEventListener(this));
    Event.observe(this.element, "keyup", this.getOnKeyUp.bindAsEventListener(this));
    
    if (this.element.form != null)
    	Event.observe(this.element.form, 'reset', this.onReset.bindAsEventListener(this));

    if($(comboName).value != '')
    {
        this.updateElement($(comboName + '_values_id_' + $(comboName).value));
    }
    else
    {
        if($(comboName + '_values_id_'))
            this.updateElement($(comboName + '_values_id_'));
    }
    
    //$(comboName + '_values_id_' + comboName.value);
    //value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
    //this.element.value = value;
  },
  /**
   * This method restore the field caption on form reset
   */
  onReset: function(event) {
	  this.element.value = "";
	  $(this.comboName).value = "";
	  this.updateCaption();
  },
  getUpdatedChoices: function() {
  		this.updateChoices(this.options.selector(this));
        this.selectPossibleValue();
  },
  getOnKeyUp: function(event) {
	  
	  if (event.keyCode == 9) {
		  return;
	  }
	  
	  // this.onKeyPress(event);
	  if (this.changed == true && this.autocompleteScript != null) {
		  // create ajax request
		  this.autocompleteScript(this.element, this.element.value, this);
	  }
	  
	  if (this.lastValue != this.element.value)
		  $(this.comboName).value = "";
	  
      this.updateCaption();
      
      // Ignore up and down key
      if (event.keyCode != 38 && event.keyCode != 40 && event.keyCode != 9)
    	  this.selectPossibleValue();
  },
  updateCaption: function() {
	  if(this.element.value == '')
		  $(this.comboName  + '_caption').show();
	  else
		  $(this.comboName  + '_caption').hide();  
  },
  /**
   * This method select the next possible item
   */
  selectPossibleValue: function() {
	  
	  var rootNode = $(this.comboName + "_values").firstChild;
	  for (var i = 0; i < rootNode.childNodes.length; i++) {
		  var item = rootNode.childNodes[i];
		  
		  if (item.firstChild == null)
			  continue;
		  
		  var itemValue = item.firstChild.nodeValue;
		  var searchValue = this.element.value;
		  
		  if (searchValue.length > 0 && 
		      itemValue.toLowerCase().substring(0, searchValue.length) == searchValue.toLowerCase()) {
			  
			  this.index = item.autocompleteIndex;
			  if (this.index != null)  {
				  var entry = this.getEntry(this.index);
				  var layer = entry.up(1); // "update" element (suggestions list)
				  var position = entry.positionedOffset();
				  var overlap = {
				    top: layer.scrollTop - position[1],
				    bottom: (position[1] + (2 * entry.getHeight())) - (layer.getHeight() + layer.scrollTop)
				  }
				  var threshold = (0.1 * entry.getHeight());
				  if(overlap.top > threshold) {
				    layer.scrollTop = position[1];
				  }
				  else if(overlap.bottom > threshold) {
				    layer.scrollTop += overlap.bottom;
				  }
				  
				  this.render();
			  }
			  break;
		  }
	  }
	  
	  // Colorize input field, if valid/invalid input (0 = invalid, 1 = part. valid, 2 = valid)
	  var compareState = 0;
	  
	  for (var i = 0; i < rootNode.childNodes.length; i++) {
		  item = rootNode.childNodes[i];
		  
		  if (item.firstChild == null)
			  continue;
		  
		  itemValue = item.firstChild.nodeValue;
		  searchValue = this.element.value;
		  
		  if (searchValue.length > 0 && 
		      itemValue.toLowerCase().substring(0, searchValue.length) == searchValue.toLowerCase()) {
			  compareState = 1;
			  
			  if (searchValue == itemValue) {
				  compareState = 2;
				  break;
			  } 
		  }
	  }
	  
	  if (compareState == 0) {
		  this.element.style.color = "#C00000";
	  }
	  else if (compareState == 1) {
		  this.element.style.color = "#004000";
	  }
	  else if (compareState == 2) {
		  this.element.style.color = "#555555";
	  }
  },

  updateElement: function(selectedElement) {

	if(!$(selectedElement))
        return;
	
    tid = selectedElement.id.sub(this.comboName + '_values_id_','');
    if (this.onChangeScript != null) {
		  this.onChangeScript(tid, this);
	}

    $(this.comboName).value =  tid;
    value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
    this.element.value = value;
    if (this.options.afterUpdateElement)
        this.options.afterUpdateElement(this.element, selectedElement);
    
    if (selectedElement == null || selectedElement.firstChild == null)
    	this.lastValue = "";
    else
    	this.lastValue = selectedElement.firstChild.nodeValue;
    
    this.selectPossibleValue();
    this.updateCaption();
    
    //$(this.comboName + '_fake').focus();
  },

  setOptions: function(options) {
    
	  
	this.options = Object.extend({
      choices: 10,
      partialSearch: false,
      partialChars: 2,
      ignoreCase: true,
      fullSearch: false,
      selector: function(instance) {
        return instance.update.innerHTML;
      }
    }, options || { });
	
	this.selectPossibleValue();
  }
});
