var script;
var SearchQueryListener = Class.create({
  initialize: function(element, results_block, script_path, send_right_away){
    if(!send_right_away) send_right_away = false;
    this.send_right_away = send_right_away;
    this.search_query = element;
    this.results_block = results_block;
    this.last_search = "";
    this.script_path = script_path;
    Event.observe(element, 'keyup', this.onKeyUp.bindAsEventListener(this));
    Event.observe(element, 'keypress', this.onKeyPress.bindAsEventListener(this));
    Event.observe(element, 'blur', this.onBlur.bindAsEventListener(this));
    this.results_listener = new ResultsSetListener(results_block, this);
  },
  onKeyPress: function(event) {
    if ((this.last_search == "") && (this.search_query.value != "")) {
      this.last_search = this.search_query.value;
    }
    if(this.results_block.visible())
      switch(event.keyCode) {
        case Event.KEY_TAB:
        case Event.KEY_RETURN:
          if (!this.selectEntry()) {
            this.hide();
            return;
          }
        case Event.KEY_ESC:
          this.hide();
          Event.stop(event);
          return;
        case Event.KEY_LEFT:
        case Event.KEY_RIGHT:
          return;
        case Event.KEY_UP:
          this.results_listener.markPrevious();
          Event.stop(event);
          return;
        case Event.KEY_DOWN:
          this.results_listener.markNext();
          Event.stop(event);
          return;
      }
    else
    if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
      (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;

  },

  onKeyUp: function(event) {
    if (this.key_timer) {
      clearTimeout(this.key_timer);
    }
    this.key_timer = setTimeout(this.deleyed_key.bind(this), 200);
  },

  deleyed_key: function() {
    el = this.search_query;
    this.key_timer = null;
    if (el.value == '') {
      this.last_search = "";
      this.hide();
    } else if(el.value.strip() == this.last_search) {
      return;
    } else {
      this.last_search = el.value.strip();
      if (script && script.parentNode) {
        document.body.removeChild(script);
      }
      script = document.createElement('script');
      script.src = this.script_path+el.value;
      script.type= 'text/javascript';
      document.body.appendChild(script);
    }
  },

  onBlur: function(event) {
    setTimeout(this.hide.bind(this), 200);
  },

  selectEntry: function() {
    if (this.results_block.visible() && this.results_listener.index >= 0) {
      this.last_search = $('sugg_'+(this.results_listener.index+1)).firstChild.nodeValue;
      this.search_query.value = this.last_search;
      this.hide();
      if(this.send_right_away) {
        this.search_query.up('form').submit();
      }
      return true;
    } else {
      return false;
    }
  },

  hide: function() {
    this.results_block.hide();
  },
  show: function(){
    this.results_block.show();
  }
});

var ResultsSetListener = Class.create({
  initialize: function(element, search_listener) {
    this.index = -1;
    this.entryCount = 0;
    this.results_block = element;
    this.search_listener = search_listener;
    Event.observe(element, 'click', this.onClick.bindAsEventListener(this));
    Event.observe(element, 'mouseover', this.onHover.bindAsEventListener(this));
  },
  update: function(suggestions){
    this.entryCount = suggestions.length;
    this.index = -1;
    if (this.entryCount > 0) {
      this.render(suggestions);
    } else {
      this.results_block.hide();
    }
  },
  render: function(suggestions) {
    ul = document.createElement('ul');
    li_i = 1;
    suggestions.each(function(suggest) {
      li = document.createElement('li');
      li.setAttribute('id', "sugg_"+li_i);
      li.appendChild(document.createTextNode(suggest));
      ul.appendChild(li);
      li_i++;
    });
    while(this.results_block.childElements().length > 0){
      this.results_block.removeChild(this.results_block.firstDescendant());
    };
    this.results_block.appendChild(ul);
    this.results_block.show();
  },
  onClick: function(event) {
     var element = Event.findElement(event, 'LI');
     if(element) {
       this.index = parseInt(element.getAttribute('id').match(/(\d+)/)[1]) - 1;
       this.search_listener.selectEntry();
       this.search_listener.search_query.focus();
     }
  },
  onHover: function(event) {
    var element = Event.findElement(event, 'LI');
    if(element) {
      autocompleteIndex = parseInt(element.getAttribute('id').match(/(\d+)/)[1]) - 1;
      if(this.index != autocompleteIndex)
      {
        this.index = autocompleteIndex;
        this.set_selected(this.index);
      }
    }
    Event.stop(event);
  },
  markPrevious: function() {
    if(this.index > 0) this.index--;
    else this.index = this.entryCount-1;
    this.set_selected(this.index);
  },

  markNext: function() {
    if(this.index < this.entryCount-1) this.index++;
    else this.index = 0;
    this.set_selected(this.index);
  },

  set_selected: function(index){
    this.results_block.select('li.selected').each(function(elem){
        elem.removeClassName('selected');
        });
    $('sugg_'+(index+1)).addClassName("selected");
  }
});
