var Livesearch = new Class({
  items: [],
  searchResults: [],
  searchTimer: [],
  searchIndex: [],
  type: [],
  errorCallbacks: [],
  callbacks: [],
  url: {
    "book": {
      "id": "/search/json/book.html",
      "search": "/search/json/books.html"
    },
    "user": {
      "id": "/search/json/user.html",
      "search": "/search/json/users.html"
    }
  },

  initialize: function()
  {
    var inputElements = $(document.body).getElements("input[class^=jsLivesearch]");

    inputElements.each( function (element) {
      var classes = element.getProperty("class").split(" ");
      classes.each( function ( className ) {
        if (className.search(/^jsLiveSearch/)) {
          this.type[element.id] = className.substr(12).toLowerCase();
        }
      }, this);
      this.searchResults[element.id] = new Array();
      this.items[element.id] = eval($(element.id+"Values").value);
      element.removeEvents();

      element.addEvent("keyup", this.search.bindWithEvent(this, element.id));

      var focusElement = function (bool) {
        livesearch.focussed = bool;
      };
      element.addEvent("focus", focusElement.bind(this,true));
      element.addEvent("blur", focusElement.bind(this,false));
      $(element.id+"Results").addEvent("focus", focusElement.bind(this,true));
      $(element.id+"Results").addEvent("blur", this.blurResults.bind(this, element.id));
      if ($(element.id+"Callback")) this.callbacks[element.id] = $(element.id+"Callback").value;
      if ($(element.id+"ErrorCallback")) this.errorCallbacks[element.id] = $(element.id+"ErrorCallback").value;
    }, this);
  },

  add: function ( id, value )
  {
    $(id+"Results").setStyle("display", "none");
    var sendObject = {"query": value};
    var me = this;
    var callback = function( data ) {
      $(id).value = "";
      me.addValue(id, data);
    }
    var json = new Json.Remote( this.url[this.type[id]].id, { onComplete: callback, method: 'POST' } );
    json.send(sendObject);
  },

  addValue: function ( id, data )
  {
    var itemId = data.id;
    if (!itemId) {
      if (this.errorCallbacks[id]) eval(this.errorCallbacks[id]+"('not_found')");
      return false;
    }
    if (this.items[id].contains(itemId)) {
      if (this.errorCallbacks[id]) eval(this.errorCallbacks[id]+"('already_exists')");
      return false;
    }
    if (this.callbacks[id]) eval(this.callbacks[id]+"(id,data)");

    this.items[id].push(data.id);
    $(id+"Values").value = Json.toString(this.items[id]);
    this.searchIndex[id]++;
  },

  search: function(e, id, doIt)
  {
    var me = this;

    if (e.code == 40) {
      var selectionBox = $(id+"Results");
      if (selectionBox.getStyle("display") == "none") return;
      for ( var i = 0; i < selectionBox.options.length; i++) {
        if (i == 0)
          selectionBox.options[i].selected = true;
        else
          selectionBox.options[i].selected = false;
      }
      $(id+"Results").focus();
      return;
    }
    if (!doIt) {
      clearTimeout(this.searchTimer[id]);
      this.searchTimer[id] = setTimeout(function() { me.search(e, id, true); }, 300);
      return;
    }
    var value = $(id).value;
    if (value.length <= 1) { $(id+"Results").setStyle("display","none"); return; }

    var sendObject = {"query": value};
    var callback = function( data ) { me.showResults(id,data); }
    var json = new Json.Remote( this.url[this.type[id]].search, { onComplete: callback, method: 'POST' } );
    json.send(sendObject);
  },

  deleteResult: function( id, index )
  {
    var newItems = [];
    var count = 0;
    for (var i = 0; i < this.items[id].length; i++) {
      if (this.items[id][i] != index) newItems[count++] = this.items[id][i];
    }
    this.items[id] = newItems;
    $(id+"Values").value = Json.toString(this.items[id]);
  },

  showResults: function ( id, results )
  {
    var me = this;
    var resultsElement = $(id+"Results");
    resultsElement.empty();
    if (results.length <= 0) {
      var option = new Element("option");
      var msg;
      switch (this.type[id]) {
        case "user": msg = "Geen gebruikers gevonden."; break;
        case "book": msg = "Geen boeken gevonden."; break;
        default:     msg = "Geen items gevonden."; break;
      }
      option.value = ""; option.innerHTML = msg;
      resultsElement.appendChild(option);
    } else {
      var link;
      buffer = "";
      for (var i = 0; i < results.length; i++) {
        this.searchResults[id][results[i].id] = results[i];

        var option = new Element("option",{
          "events": {
            "click": function () { me.setSelection(id,this.value,this.valueId); }
          }
        });
        option.value = option.innerHTML = results[i].string;
        option.valueId = results[i].id;
        resultsElement.appendChild(option);
      }
    }
    resultsElement.addEvent("keyup", function (e) {
      if (e.keyCode == 13) me.enterPressed(id);
    });
    resultsElement.addEvent("click", function (e) {
      if (this.selectedIndex >= 0) {
        me.setSelection(id,this.options[this.selectedIndex].value, this.options[this.selectedIndex].valueId);
      }
    });

    var searchSize = $(id).getSize();
    var searchPos = $(id).getPosition();
    var top = searchPos.y + searchSize.size.y;

    resultsElement.setStyle("top", top + "px");
    resultsElement.setStyle("left", searchPos.x + "px");
    resultsElement.setStyle("width", searchSize.size.x + "px");
    resultsElement.setStyle("display","");
  },

  enterPressed: function ( id )
  {
    var selectionBox = $(id+"Results");
    for ( var i = 0; i < selectionBox.options.length; i++) {
      if (selectionBox.options[i].selected) {
        this.setSelection(id,selectionBox.options[i].value, selectionBox.options[i].valueId);
      }
    }
    return true;
  },

  setSelection: function ( id, value, index )
  {
    if (index) $(id).valueId = index;
    $(id).value = value;
    $(id+"Results").setStyle("display", "none");
    //$(id+"Results").empty(); <- IE6 crashed hierop!
  },

  blurResults: function ( id )
  {
    $(id+"Results").setStyle("display","none");
  }
});

var livesearch;
window.addEvent('domready', function() { livesearch = new Livesearch(); });

