var DropDown = Class.create();
DropDown.prototype = Object.extend(new KeyCallbacks(), {
	_name              : null,
  _selector_id       : null,
  _selector          : null, //div that gets clicked to toggle
  _options           : null, //contains the options UL
  _options_id        : null,
  _selection         : null, //the div that gets updated with selected value
  _right_shadow      : null, //the div that contains the transparent shadows on right
  _right_shadow_c    : null, //the div inside that has variable height
  _selected_li       : null, 
  _last_selected_li  : null, 
	_selected_val      : null, // ex 59
  _selected_display  : null, // ex My First Project
	_last_selected_val : null,
	_canUpdate         : null,
  _ul                : null,
  _list_options      : null,
  _hidden_input      : null,
  _focusAfterSelect  : null,
  _loadingTxt        : '&nbsp;',
  _stopCallBackOnce  : null,
  _width             : 150,
  _defaultNextInput  : null,
  _open              : null,
	
	initialize : function (name, myOps) {
		var myOps = (myOps) ? $H(myOps) : $H({});

		this._myOps            = myOps;
		this._name             = name;
    this._selector_id      = name+'_dropdown';
    this._selector         = $(this._selector_id);
    this._options_id       = name+'_options';
    this._options          = $(this._options_id);
    this._ul               = this._options.select('ul')[0];
    this._canUpdate        = true;
    this._hidden_input_id  = this._name+'_hidInput';
    this._selector_down    = false;
    this._options_down     = false;
    this._focusAfterSelect = true;
    this._stopCallBackOnce = false;
    this._open             = false;
    
    if (myOps.get('shadows') == null || myOps.get('shadows') == true) {
      this._ul.insert({before:this.rightShadow()});
      this._ul.insert({after:this.bottomShadow()});
      this._right_shadow    = this._options.select('.rightShadow')[0];
      this._right_shadow_c  = this._options.select('.rightShadow .c')[0];
    }
    
    if (myOps.get('defaultNextInput')) {
      this._defaultNextInput = myOps.get('defaultNextInput');
    }
    
    if (myOps.get('onClose')) {
      this.onClose = myOps.get('onClose');
    }
    
    if (myOps.get('onOpen')) {
      this.onOpen = myOps.get('onOpen');
    }
    
    if (myOps.get('onSelect')) {
      this.onSelect = myOps.get('onSelect');
    }
    
    if (myOps.get('canUpdate') != null) {
      this._canUpdate = myOps.get('canUpdate');
    }
    
    if (myOps.get('focusAfterSelect') != null) {
      this._focusAfterSelect = myOps.get('focusAfterSelect');
    }
    
    
    
    this._loadingTxt = (myOps.get('loadingTxt')) ? myOps.get('loadingTxt') : this._loadingTxt;
    this._width      = (myOps.get('width')) ? myOps.get('width') : this._width;
    
    
    this._selector.insert({top:this.selectorTxt()});
    this._selection    = this._selector.select('.dropSelection')[0];
    
    this._ul.addClassName('dropUL');
    this._selector.addClassName('dropdown');
    this._selector.addClassName('width_'+this._width);
    this._options.addClassName('dropOptions');
    this._options.addClassName('width_'+this._width);
    
    hiddenTab         = document.createElement('input');
    $(hiddenTab).type = 'text';
    $(hiddenTab).id   = this._hidden_input_id;
    $(hiddenTab).name = this._hidden_input_id;
    document.body.appendChild($(hiddenTab));
    this._hidden_input = $(hiddenTab);
    $(this._selector).insert( { before : this._hidden_input} );	//insert
    this._hidden_input.addClassName('hiddenInputField');
    this._hidden_input.clonePosition(this._selector);
    this._hidden_input.setAttribute('autocomplete','off');
    this._hidden_input.disabled = (myOps.get('canUpdate') || myOps.get('canUpdate') == null) ? false : true;

    this.resetKeysClone = this.resetKeys.bindAsEventListener(this);
		Event.observe(this._ul, 'mouseover', this.resetKeysClone);
		
    this.toggleOptionsClone = this.toggleOptions.bindAsEventListener(this);
		Event.observe(this._selector_id, 'click', this.toggleOptionsClone);
    
    this.selectorDownClone = this.selectorDown.bindAsEventListener(this);
		Event.observe(this._selector_id, 'mousedown', this.selectorDownClone);
    
    this.selectorUpClone = this.selectorUp.bindAsEventListener(this);
		Event.observe(this._selector_id, 'mouseup', this.selectorUpClone);
    
    
    this.optionsDownClone = this.optionsDown.bindAsEventListener(this);
		Event.observe(this._options, 'mousedown', this.optionsDownClone);
    
    this.optionsUpClone = this.optionsUp.bindAsEventListener(this);
		Event.observe(this._options, 'mouseup', this.optionsUpClone);
    
    
    this.openMenuClone = this.openMenu.bindAsEventListener(this);
    this._hidden_input.observe('focus',  this.openMenuClone);
    
    this.toggleAndFocusNextClone = this.toggleAndFocusNext.bindAsEventListener(this);
    this._ul.observe('focus',  this.toggleAndFocusNextClone);
    
    this.keyEnterClone = this.keyEnter.bindAsEventListener(this);
    this._hidden_input.observe('blur',  this.keyEnterClone);
    
    
		this.setOptionItems();
		
		this.decideCloseClone = this.decideClose.bindAsEventListener(this);
		Event.observe($(document.body), 'click', this.decideCloseClone);
    
    this.userCallbacks(myOps);
    
		//make sure everything is showing at start (safari fix)
		$$("#"+this._name+"_options li").each(function(el) {
			$(el).setStyle({display:'block'});
		});
	},
  
  setOptionItems : function() {
    var tempOptions = $(this._ul).select('li');
    this._list_options = new Array();
    for (var i=0;i<tempOptions.length;i++) {
      if (!$(tempOptions[i]).hasClassName('notOption')) {
        this._list_options.push(tempOptions[i]);
      }
    }
    tempOptions = null;
    
    this.callMakeSelectionClone = this.callMakeSelection.bindAsEventListener(this);
		$(this._options_id).select('li').each(this.callMakeSelectionClone);	
  },
  
  getDisplay : function() {
    return this._selected_display;
  },
  
  getValue : function () {
    return this._selected_val;
  },
  
  getLastValue : function() {
    return this._last_selected_val;
  },
  
  keyEsc : function(e) {
    this.toggleAndFocusNext();
    Event.stop(e);
  },
  
	stopDrop : function() {
    if (this._myOps.get('shadows') == null || this._myOps.get('shadows') == true) {
      this._options.select('.rightShadow')[0].remove();
      this._options.select('.bottomShadow')[0].remove();
    }
		Event.stopObserving($(document.body), 'click', this.decideCloseClone);
    $(this._hidden_input).stopObserving('keyup', this.keyHandleClone);
	},
	decideClose : function (evt) {
    var el            = Event.element(evt);
		var foundSelector = $(el).up('#'+this._selector_id);
    var foundOptions  = $(el).up('#'+this._options_id);
    if (this._options && this._options.style.display == 'block' && !foundSelector && !foundOptions) {
      this.toggleOptions();
    }
		
	},
	decideShown : function (selEle) {
		if (this._selection  && this._canUpdate) {
			var dropOptions = $$("#"+this._options_id+" li");
			for (var i=0;i<dropOptions.length;i++) {
				var el = $(dropOptions[i]);
				if (selEle == el) {
					if (this._selection) $(this._selection).update(el.firstChild.innerHTML);
					el.style.display = 'none';
				} else {
					el.style.display = 'block';
				}
			}
		}

	},
  
  
  
  keyAccess : function(e) {
    var matches  = new Array();
    var val      = $F(this._hidden_input);
    var found    = false;
    var theMatch = false;
    var curLI; //current LI in loop
    var curHTML; //current innerHTML of div inside LI
    var pattern;
    var regex;
    
    if ($F(this._hidden_input) != '') {
      pattern = '^'+$F(this._hidden_input);
      regex   = new RegExp(pattern, 'gi');
      
      for (var i=0;i<this._list_options.length;i++) {
        curLI = this._list_options[i];
        if (curLI.visible()) {
          curHTML = curLI.down().innerHTML;
          if (curHTML.match(regex)) {
            matches.push(curLI);
          }
        }
      }
      for (var i=0;i<matches.length;i++) {
        if (matches[i].hasClassName('keySelection')) {
          theMatch = matches[i+1];
          
          if (!theMatch) {
            theMatch = matches[0];
            
          } 
          found = true;
        }
        if (found) break;
      }
      
      if (!found && matches.length > 0) {
        theMatch = matches[0];
      }
      
      if (this._ul.select('.keySelection').length > 0) {
        this._ul.select('.keySelection')[0].removeClassName('keySelection');
      }
      
      if (theMatch) {
        theMatch.addClassName('keySelection');
        
        //each of these knows if it can go up or down so call both
        this.scrollUp(this._ul, theMatch);
        this.scrollDown(this._ul, theMatch);
      }
      
    }
    this._hidden_input.value = '';
  },

	callMakeSelection : function(el) {
    if (!$(el).hasClassName('notOption')) { 
      this.makeSelectionClone =  this.makeSelection.bindAsEventListener(this);
      $(el).observe('click',this.makeSelectionClone);
    }
	},
	
	makeSelection : function(passedVal, runOnSelect) {
    var runOnSelect = (typeof(runOnSelect) == 'undefined') ? true : runOnSelect;
    var self        = this;
    
    if (typeof(passedVal) == 'string' || typeof(passedVal) == 'number') {
      selectedValue = passedVal;
    } else {
      var curEl = Event.element(passedVal);
			if (curEl.tagName != 'LI') {
				el = Event.findElement(passedVal, 'LI');
			} else {
				el = curEl;	
			}
      selectedValue = $(el).getAttribute('value');
      if ( Prototype.Browser.Gecko && $(el).hasClassName('group') && !selectedValue.match('g_')) {
        selectedValue = 'g_'+selectedValue;
      }
      
    }
    
    var selectedEl          = false;
    this._last_selected_val = this._selected_val;
		this._selected_val      = selectedValue;
    var attribValue;
    $$("#"+this._options_id+" li").each(function(el) {
      attribValue = $(el).getAttribute('value');
      
      if (Prototype.Browser.Gecko && $(el).hasClassName('group') && !attribValue.match('g_')) {
        attribValue = 'g_'+attribValue;
      }

      if (selectedValue == attribValue) {
        selectedEl = $(el);
        self._last_selected_li = self._selected_li;
        self._selected_li      = selectedEl;
        self._selected_display = self._selected_li.down().innerHTML;
      }
      
    });

    if (!selectedEl) {
			this._selection.update('Selection No Longer Exists');
			return;
		}
    this.decideShown(selectedEl);
    if (this._options.style.display == 'block') this.toggleOptions();
    if (runOnSelect && this._stopCallBackOnce == false) {
      if (this.onSelect) this.onSelect(selectedEl);
      if (this._focusAfterSelect) this.focusNextInput(this._selector.previous('.hiddenInputField'));
    } 
    
    if (this._stopCallBackOnce == true) {
      this._stopCallBackOnce = false;
    }
	
	},
  
  toggleAndFocusNext : function() {
    this.keyEnter();
    this.focusNextInput(this._selector.previous('.hiddenInputField'));
  },
  
  correctPosition : function() {
    var ops   = this._options;
    var dropD = this._selector;
    var h     = dropD.getHeight();
    var oTop  = 0;
    var oLeft = 0;
    
    oTop += h;
    if (this._myOps.get('moveLeft')) {
      oLeft += this._myOps.get('moveLeft');
      
    }
    if (this._myOps.get('moveDown')) {
      oTop += this._myOps.get('moveDown');					
    }

    ops.clonePosition(dropD,{
      setWidth: false,setHeight: false,
      offsetLeft: oLeft,offsetTop:oTop
    });
  },
  
  
  
  resetKeys : function() {
    $(this._ul).select('.keySelection').each(function(el) {
      $(el).removeClassName('keySelection');
    });
  },
  
  
  
  keyEnter : function() {
    var keySelection = $(this._ul).select('.keySelection')[0];
    if (keySelection) {
      var value = keySelection.getAttribute('value');
      this.makeSelection(value);
    }
    else {
      this.closeMenu();
    }
  },
  
  keyUp : function() {
    this.decidePreviousKeySelection(this._ul,this._list_options,'li');
  },
  
  keyDown : function() {
    this.decideNextKeySelection(this._ul,this._list_options,'li');
  },
  
  
  
  loadKeyStrokes : function() {
    $(this._ul).scrollTop = 0;
    this.keyHandleClone = this.keyHandle.bindAsEventListener(this);
    $(this._hidden_input).observe('keyup', this.keyHandleClone);
   
  },
  
  killKeyStrokes : function() {
    this.resetKeys();
    Event.stopObserving($(this._hidden_input), 'keyup', this.keyHandleClone);
  },
  
  selectorDown : function() {
    this._selector_down = true;
  },
  
  selectorUp : function() {
    this._selector_down = false;
  },
  
  optionsDown : function() {
    this._options_down = true;
  },
  
  optionsUp : function() {
    this._options_down = false;
  },
  
  closeMenu : function() {
    if (this._selector_down == false && this._options_down == false) {
      this._open = false;
      this._options.style.display = 'none';
      this.killKeyStrokes();
      if (this.onClose) this.onClose();
    }
  },
  
  openMenu : function() {
    if (this.getValue() != '' && this.getValue() != null && this._list_options.length == 1) { //if youve selected the one option, it doesnt need to open
      this.closeMenu();
      return;
    }
    this._open = true;
    if (this._myOps.get('moveMe')) {
      this.correctPosition();
    }
    if ((this._myOps.get('adjustHeight') == null && this._myOps.get('shadows') == null) || (this._myOps.get('adjustHeight') == true && this._myOps.get('shadows') == true)) {
      $(this._right_shadow).setStyle({height : '0px'}); //won't interfere with height calculation
    }
    this._options.style.display='block';
    this.loadKeyStrokes();
    if ((this._myOps.get('adjustHeight') == null && this._myOps.get('shadows') == null) || (this._myOps.get('adjustHeight') == true && this._myOps.get('shadows') == true)) {
			var h = $(this._options).getHeight();
			var newH = h-14;
			this._right_shadow_c.setStyle({height : newH+'px'});
		}
  },
	
	toggleOptions : function() {
		var ops = this._options;
		if (ops.style.display == '' || ops.style.display == 'none') {
      if (this._hidden_input.disabled == false) {
        this._hidden_input.focus();
      } else {
        this.openMenu();
      }
      if (this.onOpen) this.onOpen();
			
		} else {
			this.closeMenu();
		}
	},
  bottomShadow : function() {
    return '<div class="bottomShadow"><div class="l">&nbsp;</div><div class="c">&nbsp;</div><div class="r">&nbsp;</div></div>';
  },
  rightShadow : function() {
    return '<div class="rightShadow"><div class="t">&nbsp;</div><div class="c">&nbsp;</div></div>';
  },
  selectorTxt : function() {
    return '<div class="dropdownPad"><div class="dropSelection">'+this._loadingTxt+'</div></div>';
  }
  
});

HotKeys = {
  shiftDown    : false,
  hotstartDown : false,
  startObserving : function() {
    document.observe('keydown',HotKeys.handleKeyDown);
    document.observe('keyup',HotKeys.handleKeyUp);
  },
  stopObserving : function() {
    HotKeys.forceKeysUp();
    document.stopObserving('keydown',HotKeys.handleKeyDown);
    document.stopObserving('keyup',HotKeys.handleKeyUp);
  },
  forceKeysUp : function() {
    this.shiftDown    = false;
    this.hotstartDown = false;
  },
  handleKeyDown : function(e) {
    if (e.keyCode == Event.KEY_SHIFT) {
      HotKeys.shiftDown = true;
    }
    
    if (e.keyCode == Event.KEY_HOTSTART) {
      HotKeys.hotstartDown = true;
    }

  },
  handleKeyUp : function(e) {
    //console.log(e.keyCode, HotKeys.shiftDown,HotKeys.hotstartDown);
    if (e.keyCode == 65 && HotKeys.shiftDown && HotKeys.hotstartDown) { //a
      addActionPop();
    }
    if (e.keyCode == Event.KEY_SHIFT) {
      setTimeout("HotKeys.shiftDown = false",100);
    }
    
    if (e.keyCode == Event.KEY_HOTSTART) {
      setTimeout("HotKeys.hotstartDown = false",100);
    }
    //65 = a
    //83 = s
    
  }
}
