Ajax.Search = Class.create();

Ajax.Search.prototype = Object.extend(new Ajax.Base(),{

  initialize: function(params) {
    this.search_timeout = '';
    this.result_items = '';
    this.selected_item = '';
    this.keypress_event_listener = this.watch_keypress.bindAsEventListener(this);
    this.ignore_keys = $A(new Array(Event.KEY_DOWN,Event.KEY_UP,Event.KEY_ESC,Event.KEY_RIGHT,Event.KEY_LEFT));
    this.params = $H(params);
    if (this.params.input == undefined) {
      this.params.input = 'search';
    }
    if (!$(this.params.input)) {
      return;
    }
    if (this.params.results_container == undefined) {
      this.params.results_container = 'search_results';
    }
    if (!$(this.params.results_container)) {
      new Insertion.After($(this.params.input),' <img src="/blog/wp-content/plugins/ajax.search/img/loader-stop.gif" alt="" id="loader_stop" />');
      new Insertion.After($(this.params.input),' <img src="/blog/wp-content/plugins/ajax.search/img/loader.gif" alt="" style=\"display: none\" id="loader" />');
      new Insertion.After($(this.params.input),'<div id="' + this.params.results_container + '" style=\"display: none\"></div>');
    }
    if (this.params.search_interval == undefined) {
      this.params.search_interval = 1000;
    }
    if (this.params.loader == undefined) {
      this.params.loader = 'loader';
    }
    $(this.params.input).setAttribute('autocomplete','off');
    $(this.params.input).setAttribute('accesskey','s');
    Element.addClassName($(this.params.input),'search_box');
    Element.ancestors($(this.params.input)).each(function(a) { // stop the form from being submitted
      if (a.tagName.toLowerCase() == 'form') {
        Event.observe(a,'submit',function(e) {
          Event.stop(e);
          return false;
        });
        return;
      }
    });
    Element.nextSiblings($(this.params.input)).each(function(a) { // hide the submit button
      if (a.getAttribute('type') == 'submit') {
        a.hide();
        return;
      }
    });
    Event.observe(this.params.input,'keyup',function(e) {this.delay_search(e)}.bind(this));
  },

  delay_search: function(e) {
    if ($(this.params.input).value == '') {
      $(this.params.results_container).hide();
      return;
    }
    var key = e.keyCode;
    if (this.ignore_keys.include(key)) {
      return;
    }
    if (key == Event.KEY_RETURN && this.selected_item != '') {
      return;
    }
    this.show_loader();
    clearTimeout(this.search_timeout);
    this.search_timeout = setTimeout(function(){this.search()}.bind(this),this.params.search_interval);
  },

  search: function() {
    new Ajax.Request(this.params.url,{asynchronous:true, evalScripts:true, parameters:$({search: $(this.params.input).value}), onComplete: function(result) {
      this.display_results(result.responseText);
      this.hide_loader();
    }.bind(this)});
  },

  display_results: function(content) {
    Event.stopObserving(this.params.input, 'keydown', this.keypress_event_listener);
    this.clear_selected_items();
    this.selected_item = '';
    this.result_items = '';
    $(this.params.results_container).innerHTML = content;
    $(this.params.results_container).show();
    this.result_items = $A($(this.params.results_container).getElementsByTagName('dd'));
    if (this.result_items.length == 0) {
      this.result_items = $A($(this.params.results_container).getElementsByTagName('li'));
    }
    this.result_items.each(function(item) {
      Element.observe(item,'mouseover',function() {
        Element.addClassName(item,'active');
      }.bind(item).bind(this));
      Element.observe(item,'mouseout',function() {
        Element.removeClassName(item,'active');
      }.bind(item).bind(this));
      Element.observe(item,'click',function() {
        this.clear_selected_items();
        Element.addClassName(item,'selected');
        this.selected_item = item;
        this.goto_result();
      }.bind(this).bind(item));
    }.bind(this));
    Event.observe($(this.params.input), 'keydown', this.keypress_event_listener);
  },

  show_loader: function() {
    if (!$(this.params.loader)) { return; }
    if ($('loader_stop')) { $('loader_stop').hide();}
    $(this.params.loader).show();
  },

  hide_loader: function() {
    if (!$(this.params.loader)) { return; }
    $(this.params.loader).hide();
    if ($('loader_stop')) { $('loader_stop').show();}
  },

  clear_selected_items: function() {
    if (this.result_items == '') { return; }
    this.result_items.each(function(item) {
      Element.removeClassName(item,'selected');
    });
    this.selected_item = '';
    $A($(this.params.results_container).getElementsByTagName('dt')).each(function(dt){ 
      Element.removeClassName(dt,'selected');
    });
  },

  watch_keypress: function(e) {
    if ($(this.params.results_container).visible()) {
      switch(e.keyCode) {
        case Event.KEY_UP:
          this.select_prev();
          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(e);
          return;
        case Event.KEY_DOWN:
          this.select_next();
          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(e);
          return;
        case Event.KEY_ESC:
          $(this.params.results_container).hide();
          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(e);
          return;
        case Event.KEY_RETURN:
          this.goto_result();
          if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(e);
          return;
      }
    }
  },

  select_next: function() {
    if (this.selected_item == '') {
      if (this.is_results_header(this.result_items.first())) {
        this.selected_item = this.result_items[1];
      } else {
        this.selected_item = this.result_items.first();
      }
      Element.addClassName(this.selected_item,'selected');
      if (this.has_prev_dt(this.selected_item)) {
        Element.addClassName(Element.previous($(this.selected_item)),'selected');
      }
    } else {
      if (this.selected_item == this.result_items.last()) {
        if (this.is_results_header(this.result_items.first())) {
          var item = this.result_items[1];
        } else {
          var item = this.result_items.first();
        }
      } else {
        var item = this.result_items[this.result_items.indexOf(this.selected_item)+1];
      }
      this.clear_selected_items();
      Element.addClassName(item,'selected');
      this.selected_item = item;
      if (this.has_prev_dt(this.selected_item)) {
        Element.addClassName(Element.previous($(this.selected_item)),'selected');
      }
    }
  },

  select_prev: function() {
    if (this.selected_item == '') {
      this.selected_item = this.result_items.last();
      Element.addClassName(this.selected_item,'selected');
      if (this.has_prev_dt(this.selected_item)) {
        Element.addClassName(Element.previous($(this.selected_item)),'selected');
      }
    } else {
      if (this.selected_item == this.result_items.first() || (this.is_results_header(this.result_items.first()) && this.selected_item == this.result_items[1])) {
        var item = this.result_items.last();
      } else {
        var item = this.result_items[this.result_items.indexOf(this.selected_item)-1]
      }
      this.clear_selected_items();
      Element.addClassName(item,'selected');
      this.selected_item = item;
      if (this.has_prev_dt(this.selected_item)) {
        Element.addClassName(Element.previous($(this.selected_item)),'selected');
      }
    }
  },

  goto_result: function() {
    if ($(this.selected_item).getElementsByTagName('a').length == 0) {
      return;
    }
    setTimeout(function() { Element.addClassName($(this.selected_item),'highlight');}.bind(this),100);
    setTimeout(function() { Element.removeClassName($(this.selected_item),'highlight');}.bind(this),220);
    setTimeout(function() { Element.addClassName($(this.selected_item),'highlight');}.bind(this),300);
    setTimeout(function() { window.location = $(this.selected_item).getElementsByTagName('a')[0].href;}.bind(this),360);
  },
  
  is_results_header: function(item) {
    return Element.hasClassName(item,'search_results_header');
  },
  
  has_prev_dt: function(item) {
    return Element.previous($(item)) != null && Element.previous($(item)).tagName.toLowerCase() == 'dt'
  }
  
});