var KeyCallbacks = Class.create();
KeyCallbacks.prototype = {
  // key[command] = part of object extending
  // on[command]  = from user callback
  initialize:function(){},
  keyUp:function(){},
  keyTab:function(){},
  keyDown:function(){},
  keyEsc:function(){},
  keyEnter:function(){},
  keyAccess:function(){},
  keyDelete:function(){},
  keyBackspace:function(){},
  
  onUp:function(){},
  onTab:function(){},
  onDown:function(){},
  onEsc:function(){},
  onEnter:function(){},
  onAccess:function(){},
  onDelete:function(){},
  onBackspace:function(){},
  
  userCallbacks : function(myOps) {
    if (myOps.get('onUp')) {
      this.onUp = myOps.get('onUp');
    }
    
    if (myOps.get('onTab')) {
      this.onTab = myOps.get('onTab');
    }
    
    if (myOps.get('onDown')) {
      this.onDown = myOps.get('onDown');
    }
    
    if (myOps.get('onEsc')) {
      this.onEsc = myOps.get('onEsc');
    }
    
    if (myOps.get('onEnter')) {
      this.onEnter = myOps.get('onEnter');
    }
    
    if (myOps.get('onAccess')) {
      this.onEnter = myOps.get('onAccess');
    }
    
    if (myOps.get('onDelete')) {
      this.onDelete = myOps.get('onDelete');
    }
    
    if (myOps.get('onBackspace')) {
      this.onBackspace = myOps.get('onBackspace');
    }

  },
  
  focusNextInput : function(selectedField) {
    if (typeof(this._defaultNextInput) != 'undefined' && this._defaultNextInput) {
      this._defaultNextInput.focus();
      return;
    }
    var inputs    = $$('input');
    var nextInput = false;
    for (var i = 0; i<inputs.length;i++) {
      var curInput = inputs[i];
      
      if (nextInput == true) {
        curInput.focus();
        break;
      }
      
      if (curInput == selectedField) {
        nextInput = true;
      }
    }
  },
  
  keyHandle : function(e) {
    switch (e.keyCode) {
      case Event.KEY_UP :
        this.keyUp(e); 
        this.onUp(e);
        break;
      case Event.KEY_TAB :
        this.keyTab(e);
        this.onTab(e);
        break;
      case Event.KEY_DOWN :
        this.keyDown(e);
        this.onDown(e);
        break;
      case Event.KEY_ESC :
        this.keyEsc(e);
        this.onEsc(e);
        break;
      case Event.KEY_RETURN :
        this.keyEnter(e);
        this.onEnter(e);
        break;
      case Event.KEY_DELETE :
        this.keyDelete(e);
        this.onDelete(e);
        break;
      case Event.KEY_BACKSPACE :
        this.keyBackspace(e);
        this.onBackspace(e);
        break;
      default :
        this.keyAccess(e);
        this.onAccess(e);
        break;
    }
  },
  selectFirst : function(lis) {
    if (lis) {
      for (var i=0;i<lis.length;i++) {
        if (lis[i].visible()) {
          lis[i].addClassName('keySelection');
          break;
        }
      }
    }
  },
  
  selectLast : function(lis) {
    if (lis) {
      for (var i=lis.length-1;i>=0;i--) {
        if (lis[i].visible()) {
          lis[i].addClassName('keySelection');
          break;
        }
      }
    }
  },
  
  decidePreviousKeySelection : function(container,lis, css_rule) {
    var keySelection = $(container).select('.keySelection')[0];

    if (keySelection) {
      keySelection.removeClassName('keySelection');
      var previousLI = keySelection.previous(css_rule);

      while (previousLI && (!$(previousLI).visible() || lis.indexOf(previousLI) == -1)) {
        previousLI = (previousLI.previous(css_rule)) ? previousLI.previous(css_rule) : false;
      }

      if (previousLI) {
        previousLI.addClassName('keySelection');
        this.scrollUp(container, previousLI);

      } 
    } 
    
    var selectLast = (!keySelection || !previousLI) ? true : false;
    
    if (selectLast) {
      this.selectLast(lis);
      var maxScroll = container.scrollHeight-container.getHeight();
      if (maxScroll > 1) {
        $(container).scrollTop = 10000;
      }
    }
  },
  decideNextKeySelection : function(container,lis, css_rule) {
    var keySelection = $(container).select('.keySelection')[0];

    if (keySelection) {
      keySelection.removeClassName('keySelection');
      var nextLI = keySelection.next(css_rule);

      while (nextLI && (!$(nextLI).visible() || lis.indexOf(nextLI) == -1)) {
        nextLI = (nextLI.next(css_rule)) ? nextLI.next(css_rule) : false;
      }

      if (nextLI) {
        nextLI.addClassName('keySelection');
        this.scrollDown(container, nextLI);
        
      } 
    } 
    
    var selectFirst = (!keySelection || !nextLI) ? true : false;
    
    if (selectFirst) {
      this.selectFirst(lis);
      var maxScroll = container.scrollHeight-container.getHeight();
      if (maxScroll > 1) {
        $(container).scrollTop = 0;
      }
    }
  },
  scrollDown : function(container, scrollToElement) {
    var scrollTop = $(container).scrollTop;
    var maxScroll = container.scrollHeight-container.getHeight();
    if (maxScroll > 1) {
      while (scrollTop <= maxScroll && scrollToElement.viewportOffset()[1]+(scrollToElement.getHeight()*2) > container.up().viewportOffset()[1]+scrollToElement.up().getHeight()) {
        scrollTop           = scrollTop+1;
        container.scrollTop = scrollTop;
      }
    }

  },
 
  scrollUp : function(container, scrollToElement) {
    var scrollTop = container.scrollTop;
    var maxScroll = container.scrollHeight-container.getHeight();
    
    if (maxScroll > 1) {
      while (scrollToElement.viewportOffset()[1] < container.up().viewportOffset()[1]) {
        scrollTop           = scrollTop-1;
        container.scrollTop = scrollTop;
      }
    }
  }
}