/*
 * Navigation allows movement using the arrow keys through the search results.
 *
 * When using this library you will need to set scrollIntoView to the
 * appropriate function for your layout.  Use scrollInWindow if the container
 * is not scrollable and scrollInElement if the container is a separate
 * scrolling region.
 */
Navigation = new function() {
  this.initNavigation = function() {
    var _this = this;

    $(document).keydown(function(e) {
      _this.onkeydown(e);
    }).keyup(function(e) {
      _this.onkeyup(e);
    });

    this.navigationActive = true;
  }

  this.setNavigationActive = function(state) {
    this.navigationActive = state;
    this.clearMoveTimeout();
  }

  this.onkeyup = function(e) {
    if (!this.navigationActive) return;

    switch(e.keyCode) {
      case 37: //Event.KEY_LEFT:
      case 38: //Event.KEY_UP:
      case 39: //Event.KEY_RIGHT:
      case 40: //Event.KEY_DOWN:
        this.clearMoveTimeout();
        break;
    }
  }

  this.onkeydown = function(e) {
    if (!this.navigationActive) return;
    switch(e.keyCode) {
      case 37: //Event.KEY_LEFT:
        if (this.moveLeft()) e.preventDefault();
        break;
      case 38: //Event.KEY_UP:
        if (e.keyCode == 38 || e.ctrlKey) {
          if (this.moveUp()) e.preventDefault();
          this.startMoveTimeout(false);
        }
        break;
      case 39: //Event.KEY_RIGHT:
        if (this.moveRight()) e.preventDefault();
        break;
      case 40: //Event.KEY_DOWN:
        if (e.keyCode == 40 || e.ctrlKey) {
          if (this.moveDown()) e.preventDefault();
          this.startMoveTimeout(true);
        }
        break;
      case 13: //Event.KEY_RETURN:
        if (this.$current) e.preventDefault();
        this.select(this.$current);
        break;
    }
    if (e.ctrlKey && e.shiftKey) this.select(this.$current);
  }

  this.clearMoveTimeout = function() {
    clearTimeout(this.moveTimeout);
    this.moveTimeout = null;
  }

  this.startMoveTimeout = function(isDown) {
    if (!$.browser.mozilla && !$.browser.opera) return;
    if (this.moveTimeout) this.clearMoveTimeout();
    var _this = this;

    var go = function() {
      if (!_this.moveTimeout) return;
      _this[isDown ? 'moveDown' : 'moveUp']();
      _this.moveTimeout = setTimeout(go, 100);
    }
    this.moveTimeout = setTimeout(go, 200);
  }

  this.moveRight = function() {
  }

  this.moveLeft = function() {
  }

  this.move = function(isDown) {
  }

  this.moveUp = function() {
    return this.move(false);
  }

  this.moveDown = function() {
    return this.move(true);
  }

  /*
   * Scrolls to the given element in the scrollable element view.
   */
  this.scrollInElement = function(element, view) {
    var offset, viewHeight, viewScroll, height;
    offset = element.offsetTop;
    height = element.offsetHeight;
    viewHeight = view.offsetHeight;
    viewScroll = view.scrollTop;

    if (offset - viewScroll + height > viewHeight) {
      view.scrollTop = offset - viewHeight + height;
    }
    if (offset < viewScroll) {
      view.scrollTop = offset;
    }
  }

  /*
   * Scrolls to the given element in the window.  The second argument is
   * ignored
   */
  this.scrollInWindow = function(element, ignored) {
    var offset, viewHeight, viewScroll, height;
    offset = element.offsetTop;
    height = element.offsetHeight;
    viewHeight = window.innerHeight;
    viewScroll = window.scrollY;

    if (offset - viewScroll + height > viewHeight) {
      window.scrollTo(window.scrollX, offset - viewHeight + height);
    }
    if (offset < viewScroll) {
      window.scrollTo(window.scrollX, offset);
    }
  }
}

