CatalogChoice.CatalogSearchAutoComplete = Class.create();
CatalogChoice.CatalogSearchModel = Class.create();

Object.extend(CatalogChoice.CatalogSearchModel.prototype, {
  initialize: function(resultsContainer) {
    this.completeWindowContainer = $(resultsContainer);
  }, 
  
  selectNext: function() {
    if (this._resultsList()) {
      var current = this._selection()
      if (current) {
        newSelection = current.next(".result") || current;
      } else {
        newSelection = this._resultsList().down(".result");
      }
      
      this._select(newSelection);
    }
  },
  
  selectPrevious:  function() {
    if (this._resultsList()) {
      var current = this._selection();
      if (current) {
        newSelection = current.previous(".result") || current;
      } else {
        newSelection = this._resultsList().select(".result").last();
      }
      
      this._select(newSelection);
    }
  },
  
  hasSelection: function() {
    return this._selection();
  },
  
  triggerSelection: function() {
    var selection = this._selection();
    if (selection) {
      var link = selection.down("a[href]");
      if (link.onclick) {
        link.onclick();
      } else {
        window.location = link.readAttribute("href");
      }
    }
  },
  
  _selection: function() {
    return this._resultsList() && this._resultsList().down(".selected");
  },
  
  _resultsList: function() {
    return this._completeWindow() && this._completeWindow().down(".results-list");
  },
  
  hide: function() {
    this._clearSelection();
    
    this._completeWindow().setStyle({"display": "none"});
  },
  
  _clearSelection: function() {
    this._completeWindow().select(".results-list .selected").invoke("removeClassName", "selected")
  },
  
  _completeWindow: function() {
    if (!this._completeWindowElement) {
      var element = $(document.createElement('div'));
    
      element.writeAttribute("id", "autocomplete-results")
      element.setStyle({
        display: 'none',
        position: 'absolute'
      });

      this.completeWindowContainer.appendChild(element);
      this._completeWindowElement = element;
    };
    
    return this._completeWindowElement;
  }, 
  
  show: function(elementToClone, results) {
    var completeWindow = this._completeWindow();
    completeWindow.setStyle({display: ''});
    completeWindow.innerHTML = results;
    completeWindow.clonePosition(elementToClone, {setHeight: false, offsetTop: elementToClone.offsetHeight});
    completeWindow.select(".result").invoke("observe", "mouseover", this._entryMousedOver.bindAsEventListener(this))
  },
  
  _entryMousedOver: function(event) {
    var element = event.element();
    if(!element.hasClassName("result")) {
      element = element.up(".result");
    }
    
    this._select(element);
  }, 
  
  _select: function(entry) {
    this._clearSelection();
    entry.addClassName("selected");
  }
});

Object.extend(CatalogChoice.CatalogSearchAutoComplete.prototype, {
  initialize: function(element, args) {
    this.element = $(element);
    this.url = args.url;
    this._setUp();
    this.resultsModel = new CatalogChoice.CatalogSearchModel(args.resultsContainer);
  },
  
  _setUp: function() {
    new Form.Element.Observer(this.element, 1.0, this._performAutoComplete.bind(this));
    var hide = this._hideResults.bind(this);
    this.element.observe('blur', function() { hide.delay(1.1); });
    this.element.observe(window.opera ? 'keypress':'keydown', this.keyPressed.bind(this)); //this.el, window.opera ? 'keypress':'keydown', this.onKeyPress.bind(this));
  },
  
  keyPressed: function(e) {
    switch (e.keyCode) {
      case Event.KEY_ESC:
        this._hideResults();
        break;
      case Event.KEY_UP:
        this.resultsModel.selectPrevious();
        break;
      case Event.KEY_DOWN:
        this.resultsModel.selectNext();
        break;
      case Event.KEY_RETURN:
        if (this.resultsModel.hasSelection()) {
          this.resultsModel.triggerSelection();
        } else {
          return;
        }
        break;
      default: 
        return;
    }
    
    Event.stop(e);
  },
  
  _performAutoComplete: function(element, value) {
    if (value && !value.blank()) {
      new Ajax.Request(this._urlFor(value), {
        method: 'get',
        onSuccess: function(response) {
          if (value == this.element.getValue()) {
            this._resultsArrived(response);
          }
        }.bind(this)
      });
    } else {
      this._hideResults();
    }
  },

  _urlFor: function(value) {
    return this.url.gsub("_query_", encodeURIComponent(value));
  },

  _resultsArrived: function(response) {
    var results = response.responseText;
    if (results) {
      this._showResults(results)
    } else {
      this._hideResults();
    }
  },
  
  _hideResults: function() {
    this.resultsModel.hide(); 
  }, 
  
  _showResults: function(results) {
    this.resultsModel.show(this.element, results);
  }
});