function SelectionList(mainElement, 
		       enabledClassName, 
		       disabledClassName,
		       invisibleClassName,
		       parameters)
{
  this.getState =
  function()
  {
    return _parameters.state;
  };

  this.setState =
  function(state)
  {
    var i;

    if(state == SelectionList.STATE_ENABLED){
      _mainElement.className = _enabledClassName; 
      _parameters.state = state;
    }
    else if(state == SelectionList.STATE_DISABLED){
      
      _mainElement.className = _disabledClassName;

      for(i in _scrollUpButtons){
	_scrollUpButtons[i].setState(GuiItem.STATE_DISABLED);
      }
      for(i in _scrollDownButtons){
	_scrollDownButtons[i].setState(GuiItem.STATE_DISABLED);
      }      
      _parameters.state = state;
    }
    else if(state == SelectionList.STATE_INVISIBLE){
    
      _mainElement.className = _invisibleClassName;
   
      for(i in _scrollUpButtons){
	_scrollUpButtons[i].setState(GuiItem.STATE_INVISIBLE);
      }
      for(i in _scrollDownButtons){
	_scrollDownButtons[i].setState(GuiItem.STATE_INVISIBLE);
      }

      _parameters.state = state;
    }
  };

  this.clear =
  function()
  {
    _items = new Array();
    _selectedIndex = null;
    _minVisibleIndex = 0;
    _maxVisibleIndex = 0;
    _updateList();
  };

  this.addItem =
  function(item)
  {
    _items.push(item);

    if(_maxVisibleIndex < (_parameters.size - 1)){
      _maxVisibleIndex++;
    }

    _updateList();
  };

  this.addArrayOfItems =
  function(items)
  {
    for(i in items){
      _items.push(items[i]);
    }
    
    if(_maxVisibleIndex < (_parameters.size - 1)){
      if(_items.length > _parameters.size){
	_maxVisibleIndex = _parameters.size - 1;
      }
      else{
	_maxVisibleIndex = _items.length - 1;
      }
    }

    _updateList();
  };


  this.getLength =
  function()
  {
    return _items.length;
  };

  this.setSelectedIndex =
  function(index)
  {
    if(index === null){
      _selectedIndex = null;
    }
    else if(index >= 0 && index < _items.length){
      _selectedIndex = index;
    }
    _updateList();
  };


  this.getSelectedIndex =
  function()
  {
    return _selectedIndex;
  };


  this.getSelectedItem =
  function()
  {
    //  alert(_selectedIndex + " " + _items[_selectedIndex]);

    if(_selectedIndex === null){
      return null;
    }
    else{
      return _items[_selectedIndex];
    }
  };

  this.getItems =
  function()
  {
    return _items;
  };

  this.selectNextItem =
  function()
  {
    if(_selectedIndex === null){
      /* DO NOTHING */
    }
    else if(_selectedIndex < (_items.length - 1)){

      _selectedIndex++;
    
      _items[_selectedIndex - 1].setState(SelectionList.Item.STATE_ENABLED);
      _items[_selectedIndex].setState(SelectionList.Item.STATE_SELECTED);
     
      if(_maxVisibleIndex < _items.length - 1){
	if(_selectedIndex > (_minVisibleIndex + _parameters.selectNextScrollLimit)){

	  _this.scrollDown();

	}
      }

      for(var i in _selectionChangeCBFs){
       	_selectionChangeCBFs[i](_this);
      }
    }
    return _selectedIndex;
  };

  this.selectPreviousItem =
  function()
  {
    if(_selectedIndex === null){
      /* DO NOTHING */
    }
    else if(_selectedIndex === 0){
      /* DO NOTHING */
    }
    else if(_selectedIndex > 0){
  
      _selectedIndex--;
   
      _items[_selectedIndex + 1].setState(SelectionList.Item.STATE_ENABLED);
      _items[_selectedIndex].setState(SelectionList.Item.STATE_SELECTED);

      if(_minVisibleIndex > 0){

	if(_selectedIndex < (_minVisibleIndex + _parameters.selectPreviousScrollLimit)){
	 
	  _this.scrollUp();
	}
      }
    
      for(var i in _selectionChangeCBFs){
       	_selectionChangeCBFs[i](_this);
      }
    }
    return _selectedIndex;
  };

  this.scrollDown =
  function()
  {
    if(_maxVisibleIndex < (_items.length - 1)){
      
      _maxVisibleIndex++;
      _minVisibleIndex++;

      var numberOfNodes = _mainElement.childNodes.length;

      for(var i = numberOfNodes - 1; i >= 0; i--){
	
	_mainElement.replaceChild(_items[i + _minVisibleIndex].getDomNode(), _mainElement.childNodes[i]);
      }	
      _updateScrollButtons();
    }
  };

  this.scrollUp =
  function()
  {
    if(_minVisibleIndex > 0){

      _maxVisibleIndex--;
      _minVisibleIndex--;

      var numberOfNodes = _mainElement.childNodes.length;

      for(var i = 0; i < numberOfNodes; i++){
	
	_mainElement.replaceChild(_items[i + _minVisibleIndex].getDomNode(), _mainElement.childNodes[i]);
      }	
      _updateScrollButtons();    
    }
  };


  this.addScrollUpButton =
  function(button, scrollDelay)
  {
    button.addMouseClickCBF(_scrollUpButtonHandler);
    button.setState(GuiItem.STATE_INVISIBLE);
    button.addMouseDownCBF(_scrollUpButtonHandler, scrollDelay);
    _scrollUpButtons.push(button);
  };

  this.addScrollDownButton =
  function(button, scrollDelay)
  {
    button.addMouseClickCBF(_scrollDownButtonHandler);
    button.setState(GuiItem.STATE_INVISIBLE);
    button.addMouseDownCBF(_scrollDownButtonHandler, scrollDelay);
    _scrollDownButtons.push(button);
  };

  this.addSelectionChangeCBF =
  function(cbf)
  {
    _selectionChangeCBFs.push(cbf);
  }

  var _scrollDownButtonHandler =
  function()
  {
    if(_selectedIndex === null){
      _this.setSelectedIndex(0);
    }
    else if(_maxVisibleIndex >= (_items.length - 1)){
      /* DO NOTHING */
    }
    else{
      _this.scrollDown();
      //  _this.setSelectedIndex(_selectedIndex + 1);
    }
  };

  var _scrollUpButtonHandler =
  function()
  {
    if(_selectedIndex === null){
      _this.setSelectedIndex(0);
    }
    else if(_minVisibleIndex <= 0){
      /* DO NOTHING */
    }
    else{
      _this.scrollUp();
      //      _this.setSelectedIndex(_selectedIndex - 1);
    }
  };


  var _updateList =
  function()
  {       
    var numberOfNodes = _mainElement.childNodes.length;

    for(var i = numberOfNodes - 1; i >= 0; i--){
      _mainElement.removeChild(_mainElement.childNodes[i]);
      numberOfNodes--;
    }
  
    var j = 0; 

    for(var i = _minVisibleIndex;
	i < _items.length && i <= _maxVisibleIndex;
	i++)
    {
      if(_selectedIndex === null){
	_items[i].setState(SelectionList.Item.STATE_ENABLED);
      }
      else if(i == _selectedIndex){
	_items[i].setState(SelectionList.Item.STATE_SELECTED);
      }
      else{
	_items[i].setState(SelectionList.Item.STATE_ENABLED);
      }

      if(j < numberOfNodes){
       	_mainElement.replaceChild(_items[i].getDomNode(), _mainElement.childNodes[j]) 
	  j++;
      }
      else{
      	_mainElement.appendChild(_items[i].getDomNode());
      }
    }
    _updateScrollButtons();   
  };


  var _updateScrollButtons =
  function()
  {
    if(_items.length > _parameters.size){

      var i;

      for(i in _scrollUpButtons){

	if(_minVisibleIndex === null || _minVisibleIndex <= 0){
	  _scrollUpButtons[i].setState(GuiItem.STATE_DISABLED);
	}
	else{
	  _scrollUpButtons[i].setState(GuiItem.STATE_ENABLED);
	}
      }
      for(i in _scrollDownButtons){
	if(_maxVisibleIndex >= (_items.length - 1)){
	  _scrollDownButtons[i].setState(GuiItem.STATE_DISABLED);
	}
	else{
	  _scrollDownButtons[i].setState(GuiItem.STATE_ENABLED);
	}
      }
    }
    else{

      var i;

      for(i in _scrollUpButtons){
	_scrollUpButtons[i].setState(GuiItem.STATE_INVISIBLE);
      }
      for(i in _scrollDownButtons){
	_scrollDownButtons[i].setState(GuiItem.STATE_INVISIBLE);
      }
    }
  };


  var _this = this;
  var _mainElement = mainElement;

  var _enabledClassName = enabledClassName;
  var _disabledClassName = disabledClassName;
  var _invisibleClassName = invisibleClassName;
  
  var _items = new Array();
  var _selectedIndex = null;

  var _parameters = parameters;
  var _minVisibleIndex = 0;
  var _maxVisibleIndex = _parameters.size - 1;


  var _scrollUpButtons = new Array();
  var _scrollDownButtons = new Array();

  var _selectionChangeCBFs = new Array();

  this.setState(_parameters.state);
}


SelectionList.STATE_ENABLED = 1;
SelectionList.STATE_DISABLED = 2;
SelectionList.STATE_INVISIBLE = 3;

SelectionList.parameters =
function(size,
	 selectNextScrollLimit,
	 selectPreviousScrollLimit,
	 state)
{
  this.size = size;

  if(selectNextScrollLimit < 0){
    this.selectNextScrollLimit = 0;
  }
  else if(selectNextScrollLimit > (size - 1)){
    this.selectNextScrollLimit = size - 1;
  }
  else{
    this.selectNextScrollLimit = selectNextScrollLimit;
  }

  if(selectPreviousScrollLimit < 0){
    this.selectPreviousScrollLimit = 0;
  }
  else if(selectPreviousScrollLimit > (size - 1)){
    this.selectPreviousScrollLimit = size - 1;
  }
  else{
    this.selectPreviousScrollLimit = selectPreviousScrollLimit;
  }

  this.state = state;
};



SelectionList.Item =
function(domNode,
         initialData,
         initialState)
{
  this.getState =
  function()
  {
    return _guiItem.getState();
  };

  this.setState =
  function(state)
  {
    _guiItem.setState(state);
  };

  this.getData =
  function()
  {
    return _guiItem.getData();
  };

  this.setData =
  function(data)
  {
    _guiItem.setData(data);
  };

  this.getDomNode =
  function()
  {
    return _guiItem.getDomNode();
  };

  this.getMouseOver =
  function()
  {
    return _guiItem.getMouseOver();
  };

  this.getMouseDown =
  function()
  {
    return _guiItem.getMouseDown();
  };

  this.addStateChangeCBF =
  function(cbf)
  {
    _guiItem.addStateChangeCBF(cbf);  
  };

  this.addMouseClickCBF =
  function(cbf)
  {
    _guiItem.addMouseClickCBF(cbf);  
  };

  this.addMouseEnterCBF =
  function(cbf)
  {
    _guiItem.addMouseEnterCBF(cbf);
  };

  this.addMouseLeaveCBF =
  function(cbf)
  {
    _guiItem.addMouseLeaveCBF(cbf);
  };

  this.addMousePressCBF =
  function(cbf)
  {
    _guiItem.addMousePressCBF(cbf);
  };

  this.addMouseReleaseCBF =
  function(cbf)
  {
    _guiItem.addMouseReleaseCBF(cbf);
  };

  this.addMouseDownCBF =
  function(cbf, interval)  
  {
    _guiItem.addMouseDownCBF(cbf, interval);
  };

  this.getGuiItem = 
  function()
  {
    return _guiItem;
  };

  /* Private part below! */	
 
  var _initGuiItem =
  function(domNode, initialData, initialState, cbo)
  {
    var stateInfos = new Array();
    stateInfos.push(new GuiItemBase.StateInfo(SelectionList.Item.STATE_ENABLED,
                                              GuiItemBase.StateInfo.STATE_TYPE_ACTIVE));
    stateInfos.push(new GuiItemBase.StateInfo(SelectionList.Item.STATE_SELECTED,
                                              GuiItemBase.StateInfo.STATE_TYPE_ACTIVE));
    stateInfos.push(new GuiItemBase.StateInfo(SelectionList.Item.STATE_DISABLED,
                                              GuiItemBase.StateInfo.STATE_TYPE_PASSIVE));
    stateInfos.push(new GuiItemBase.StateInfo(SelectionList.Item.STATE_INVISIBLE,
                                              GuiItemBase.StateInfo.STATE_TYPE_PASSIVE));
 
    return new GuiItemBase(domNode, initialData, stateInfos, initialState, cbo);
  }
 
  var _this = this;
  var _guiItem = _initGuiItem(domNode, initialData, initialState, _this);
};

SelectionList.Item.STATE_ENABLED = 1;
SelectionList.Item.STATE_SELECTED = 2;
SelectionList.Item.STATE_DISABLED = 3;
SelectionList.Item.STATE_INVISIBLE = 4;

SelectionList.Item.StyleManager =
function(styles)
{
  this.addSelectionListItem =
  function(selectionListItem)
  {  
    _guiItemStyleManager.addGuiItem(selectionListItem);  
  };

  var _initGuiItemStyleManager =
  function(styles)
  {
    var styleArray = new Array();  
    
    styleArray[SelectionList.Item.STATE_ENABLED] = new Array();
    styleArray[SelectionList.Item.STATE_ENABLED][GuiItemBase.MOUSE_STATE_NO_MOUSE] = styles['enabled']['noMouse'];
    styleArray[SelectionList.Item.STATE_ENABLED][GuiItemBase.MOUSE_STATE_MOUSE_OVER] = styles['enabled']['mouseOver'];
    styleArray[SelectionList.Item.STATE_ENABLED][GuiItemBase.MOUSE_STATE_MOUSE_DOWN] = styles['enabled']['mouseDown'];
 
    styleArray[SelectionList.Item.STATE_SELECTED] = new Array();
    styleArray[SelectionList.Item.STATE_SELECTED][GuiItemBase.MOUSE_STATE_NO_MOUSE] = styles['selected']['noMouse'];
    styleArray[SelectionList.Item.STATE_SELECTED][GuiItemBase.MOUSE_STATE_MOUSE_OVER] = styles['selected']['mouseOver'];
    styleArray[SelectionList.Item.STATE_SELECTED][GuiItemBase.MOUSE_STATE_MOUSE_DOWN] = styles['selected']['mouseDown'];

    styleArray[SelectionList.Item.STATE_DISABLED] = new Array();
    styleArray[SelectionList.Item.STATE_DISABLED][GuiItemBase.MOUSE_STATE_NO_MOUSE] = styles['disabled']['noMouse'];
    styleArray[SelectionList.Item.STATE_DISABLED][GuiItemBase.MOUSE_STATE_MOUSE_OVER] = styles['disabled']['mouseOver'];
    styleArray[SelectionList.Item.STATE_DISABLED][GuiItemBase.MOUSE_STATE_MOUSE_DOWN] = styles['disabled']['mouseDown'];
 
    styleArray[SelectionList.Item.STATE_INVISIBLE] = new Array();
    styleArray[SelectionList.Item.STATE_INVISIBLE][GuiItemBase.MOUSE_STATE_NO_MOUSE] = styles['invisible']['noMouse'];
    styleArray[SelectionList.Item.STATE_INVISIBLE][GuiItemBase.MOUSE_STATE_MOUSE_OVER] = styles['invisible']['mouseOver'];
    styleArray[SelectionList.Item.STATE_INVISIBLE][GuiItemBase.MOUSE_STATE_MOUSE_DOWN] = styles['invisible']['mouseDown'];   
 
    return new GuiItemBase.StyleManager(styleArray);
  };

  var _guiItemStyleManager = _initGuiItemStyleManager(styles);    
};
