/*
 * After you create an instance you can set properties.
 * When you are done configuring call start() to start it.
 */
 // TODO Put example uses together. Make tab examples, menus and so on.
 // TODO Finish documenting this. And create JSDocs.
function ListItemManager(
	doc, listId, startingIndex,
	activeClassName, deactiveClassName
) {
	this._setMax = function( x ) {
		if ( x!=null || x !=undefined ) {_max = x; }
		if( _maxDisplayElem != null ) {
			_maxDisplayElem.innerHTML = _max;
		}
	};
	
	var _isStarteded = false;
	var _list = doc.getElementById( listId );
	var _items = _list.childNodes;
	var _min = 1;
	var _max = null;
	this._setMax( _items.length );
	
	var _activeClassName = activeClassName;
	var _deactiveClassName = deactiveClassName;
	var _minClassName = null;
	var _maxClassName = null;
	
	var _nextElem = null;
	var _previousElem = null;

	var _selectedElement = null;
	var _selectedElementI = null;
	var _activeDisplayElem = null;
	var	_maxDisplayElem = null;
	
	
	this.getItems = function() {
		return _items;
	};
	
	this._setSelectedElementI = function( x ) {
		_selectedElementI = x;
		if( _activeDisplayElem != null ) {
			_activeDisplayElem.innerHTML = _selectedElementI;
		}
	};
	
	/*
	 * Set the selected item.
	 * i is the index number (base of 1)
	 */
	this.setSelected = function( i ) {
		if ( i >= _min && i <= _max ) {
		
			/*alert("L: " + _list.id + "  \nP: " + _previousElem.id);*/
		
			// Deselect.
			// If there is no record of current selection deselect all.
			if ( _selectedElement == null ) {
				for ( var n = 0; n < _items.length; n++ ) {
					removeClassName( _items[n], _activeClassName   );
					addClassName(    _items[n], _deactiveClassName );
				}
			} 
			// Else deselect the current.
			else {
				removeClassName( _selectedElement, _activeClassName   );
				addClassName(    _selectedElement, _deactiveClassName );
			}
		
			// Change the next and previous element's class
			if ( _nextElem != null ) {
				if ( i == _max ) {
					addClassName(    _nextElem, _maxClassName );
				} else {
					removeClassName( _nextElem, _maxClassName );
				}
			}
			if ( _previousElem != null ) {
				if ( i == _min ) {
					addClassName(    _previousElem, _minClassName );
				} else {
					removeClassName( _previousElem, _minClassName );
				}
			}
			
			
			// Set the selection.
			removeClassName( _items[i-1], _deactiveClassName );
			addClassName(    _items[i-1], _activeClassName   );
			
			// Store for next time.
			_selectedElement = _items[i-1];
			this._setSelectedElementI( i );
		}
		
	};
	
	/*
	 * "inner class"
	 * Used when setting click event handlers. n is the item to select.
	 * There are 2 special values. "c+1" and "c-1" = current -1 or current +1 (for next and previous)
	 */
	var ClickConfig = function( manager, n ) {
		var _n = n;
		this.onclick = function() {
			if ( _n == "c+1" ) {
				manager.selectNext();
			} else if ( _n == "c-1" ) {
				manager.selectPrevious();
			} else {
				manager.setSelected(_n);
			}
		}
	};
		
	/*
	 * Puts an onclick on each element in the array. The array must have the same number of
	 * elements as there are elements being managed.
	 * The second argument is what to set the hrefs too if the elements are anchors.
	 */
	this.registerElementsAsSelectors = function( elems, hrefValue ) {
		if ( elems.length == _max ) {
			for ( var n = 1; n <= elems.length; n++ ) {
				var elem = elems[n-1];
				addEvent(
					elem,
					'click',
					new ClickConfig( this, n ).onclick
				);
				// TODO This is done a few times. Make it into a function.
				if ( elem.tagName == "a" || elem.tagName == "A" ) {
					elem.getAttributeNode("href").value = hrefValue;
				}
			}
		} else {
			alert( "Error. The length of elements and number of items being managed are not the same." );
		}
	};
	
	this.selectNext = function() {
		this.setSelected( _selectedElementI + 1 );
	};
	this.selectPrevious = function() {
		this.setSelected( _selectedElementI - 1 );
	};
	
	this.registerElementAsNext = function( elem, hrefValue ) {
		addEvent(
			elem,
			'click',
			new ClickConfig( this, "c+1" ).onclick
		);
		
		if ( elem.tagName == "a" || elem.tagName == "A" ) {
			elem.getAttributeNode("href").value = hrefValue;
		}
	};
	this.setNextElem = function( elem, maxClassName ) {
		_nextElem = elem;
		_maxClassName = maxClassName;
		if ( _isStarteded ) {
			// So classes are set correctly.
			this.setSelected( _selectedElementI );
		}
	};
	
	this.registerElementAsPrevious = function( elem, hrefValue ) {
		addEvent(
			elem,
			'click',
			new ClickConfig( this, "c-1" ).onclick
		);
		
		if ( elem.tagName == "a" || elem.tagName == "A" ) {
			elem.getAttributeNode("href").value = hrefValue;
		}
		
	};
	this.setPreviousElem = function( elem, minClassName ) {
		_previousElem = elem;
		_minClassName = minClassName;
		if ( _isStarteded ) {
			// So classes are set correctly.
			this.setSelected( _selectedElementI );
		}
	};
	
	this.registerElementAsDisplay = function( activeDisplayElem, maxDisplayElem ) {
		_activeDisplayElem = activeDisplayElem;
		_maxDisplayElem = maxDisplayElem;
		if ( _isStarteded ) {
			// So classes are set correctly.
			this._setMax();
			this.setSelected( _selectedElementI );
		}
	};
	
	this.start = function() {
		if ( !_isStarteded ) {
			// Set a start.
			if ( startingIndex == null || startingIndex == undefined ) {
				this.setSelected( _min );
			} else {
				this.setSelected( startingIndex );
			}
		}
		_isStarteded = true;
	};
	
}

/*
 * "static" methods
 */
 function registerToManagers( managers, selectors, previous, next, hrefs) {
	for ( var i=0; i < managers.length; i++) {
		var manager = managers[i];
		var hrefValue = hrefs[i];
		manager.registerElementsAsSelectors( selectors, hrefValue );
		manager.registerElementAsPrevious( previous, hrefValue );
		manager.registerElementAsNext( next, hrefValue );
	}
}

function startManagers( managers ) {
	for ( var i=0; i < managers.length; i++) {
		var manager = managers[i];
		manager.start();
	}
}
	
// ======================================================
/** TODO Should use code from a reusable library. (using JSAN)  */
function removeClassName( element, classname ) {
	if ( classname != null ) {
		var indexOfClassName = (element.className).indexOf( " " + classname );
		if ( indexOfClassName != -1 ) {
			var endOfClassName = indexOfClassName + classname.length+1;
			element.className =
				(element.className).substring( 0, indexOfClassName )
				+ (element.className).substring( endOfClassName, (element.className).length  );
		}
	}
}
function addClassName( element, classname ) {
	if ( classname != null ) {
		if ( (element.className).indexOf(classname) == -1 ) {
			element.className += " " + classname;
		}
	}
}
function retrieveFirstElement( elem, tagName ) {
	var anchors = new Array();
	for( var i=0; i < elem.length; i++ ) {
		anchors[i] = elem[i].getElementsByTagName(tagName)[0];
	}
	return anchors;
}
// ======================================================

// ======================================================
// TODO move to another class. This should be how we are doing it in JSAN. Check. Make sure I'm not donig anythiong really stupid.
// TODO Remove from here and from the lucene javascript file and use the JSAN version.
function addEvent(obj, evType, fn) { 
 if (obj.addEventListener){ 
   obj.addEventListener(evType, fn, false); 
   return true; 
 } else if (obj.attachEvent){ 
   var r = obj.attachEvent("on"+evType, fn); 
   return r; 
 } else { 
   return false; 
 } 
}
// ======================================================