/**************************************************
 * The Option class
 * @param elemId the id of the page element for this option
 * @param value the value of this option
 **************************************************/
function Option(elemId, value) {
	this.elemId = elemId;
	this.value = value;
	this.selected = false;
		
	// methods

	/**
	 * selects this Option
	 */
	this.select=function() {
		var elem = document.getElementById(this.elemId);
		this.setStyleSelect(elem);
		this.selected = true;
	};
	
	/**
	 * deselects this Option
	 */
	this.deselect=function() {
		var elem = document.getElementById(this.elemId);
		this.setStyleDeselect(elem);
		this.selected = false;
	};
}

var optionGroups = new Array(); // this should be populated with OptionGroups

/*********************************************************
 * The OptionGroup class
 * @param name the name of the parameter that will be set
 * @param setStyleSelect the function to call that changes the style of the selected element
 * @param setStyleDeselect the function to call that changes the style of the deselected element
 *********************************************************/
function OptionGroup(name, setStyleSelect, setStyleDeselect) {
	this.name = name;
	this.setStyleSelect = setStyleSelect;
	this.setStyleDeselect = setStyleDeselect;
	
	this.options = new Array(); // stores the options
	
	// methods
	this.addOption = function(option) {
		// set the functions for selecting and deselecting
		option.setStyleSelect = this.setStyleSelect;
		option.setStyleDeselect = this.setStyleDeselect;
		this.options.push(option);
	};
	
	this.getSelectedValue = function() {
		for (var i = 0; i < this.options.length; i++) {
			var option = this.options[i];
			if (option.selected) {
				return option.value;
			}
		}
	};
	
	/**
	 * Selects the option with the given value
	 * @param value the value of the option that should be selected
	 */
	this.selectOptionByValue = function(value) {
		// selects this option and unselects the other options
		for (var i = 0; i < this.options.length; i++) {
			var option = this.options[i];
			if (option.value == value) {
				// select this option
				option.select();
			}
			else {
				// deselect this option
				option.deselect();
			}
		}			
	};
	
	/**
	 * Selects the option with the given elemId
	 * @param elemId the elemId of the option that should be selected
	 */
	this.selectOptionByElemId = function selectOptionByElemId(elemId) {
		// selects this option and unselects the other options
		for (var i = 0; i < this.options.length; i++) {
			var option = this.options[i];
			if (option.elemId == elemId) {
				// select this option
				option.select();
			}
			else {
				// deselect this option
				option.deselect();
			}
		}
	};
	
	optionGroups.push(this); // add this OptionGroup to the set of OptionGroups
}

/**
 * Given the name of an OptionGroup, returns that OptionGroup
 * @param name the name of the OptionGroup to return
 * @return OptionGroup the OptionGroup with the given name
 */
function getOptionGroupByName(name) {
	// go through all of the option groups
	for (var i = 0; i < optionGroups.length; i++) {
		var og = optionGroups[i];
		if (og.name == name) {
			return og;
		}
	}
}

/**
 * Makes the given element's font bold
 * @param elem the element whose font will be changed
 */
function selectBold(elem) {
	elem.style.fontWeight="bold";
}

/**
 * Makes the given element's font normal
 * @param elem the element whose font will be changed
 */
function deselectBold(elem) {
	elem.style.fontWeight="normal";
}

/**
 * Makes the given element visible
 * @param elem the element that will be made invisible
 */
function setVisible(elem) {
	elem.style.display="block";
}

/**
 * Makes the given element invisible
 * @param elem the element that will be made invisible
 */
function setInvisible(elem) {
	elem.style.display="none";
}

/**
 * Makes the given element have the "selected" color
 * @param elem the element that will change color
 */
function selectColor(elem) {
	elem.style.backgroundColor="#DDDDDD";
}

/**
 * Makes the given element have the "deselected" color
 * @param elem the element that will change color
 */
function deselectColor(elem) {
	elem.style.backgroundColor="#AAAAAA";
}

/**
 * Makes the given element have the "mouse over" color
 * @param elem the element that will change color
 */
function mouseOverColor(elem) {
	elem.style.backgroundColor="#EEEEEE";
}


var tabGroups = new Array();

/*************************************
 * TabGroup class
 * @param the name of this TabGroup
 * @param setPageVisible the function to call to make the tabPageElem visible
 * @param setPageInvisible the function to call to make the tabPageElem invisible
 * @param setTabSelected the function to call to make the tabElem selected
 * @param setTabDeselected the function to call to make the tabElem deselected
 *************************************/
function TabGroup(name, setPageVisible, setPageInvisible, setTabSelected, setTabDeselected, setMouseOver) {
	this.name = name;
	this.tabs = new Array();
	
	this.setPageVisible = setPageVisible;
	this.setPageInvisible = setPageInvisible;	
	this.setTabSelected = setTabSelected;
	this.setTabDeselected = setTabDeselected;
	this.setMouseOver = setMouseOver;
	
	
	this.addTab = function(tab) {
		// set methods
		tab.setPageVisible = this.setPageVisible;
		tab.setPageInvisible = this.setPageInvisible;	
		tab.setTabSelected = this.setTabSelected;
		tab.setTabDeselected = this.setTabDeselected;
		tab.setMouseOver = this.setMouseOver;
		this.tabs.push(tab);
	};
	
	this.getSelectedValue = function() {
		for (var i = 0; i < this.tabs.length; i++) {
			var tab = this.tabs[i];
			if (tab.selected) {
				return tab.value;
			}
		}
	};
	
	/**
	 * Selects the tab with the given value
	 * @param value the value of the option that should be selected
	 */
	this.selectTabByValue = function(value) {
		// selects this tab and unselects the other tabs
		for (var i = 0; i < this.tabs.length; i++) {
			var tab = this.tabs[i];
			if (tab.value == value) {
				// select this tab
				tab.select();
			}
			else {
				// deselect this tab
				tab.deselect();
			}
		}			
	};
	
	this.mouseOver = function(value) {
		// find the tab
		var foundTab = false;
		for (var i = 0; i < this.tabs.length && !foundTab; i++) {
			var tab = this.tabs[i];
			if (tab.value == value) {
				tab.mouseOver();
				foundTab = true;
			}
		}
	};
	
	this.mouseOut = function(value) {
		// find the tab
		var foundTab = false;
		for (var i = 0; i < this.tabs.length && !foundTab; i++) {
			var tab = this.tabs[i];
			if (tab.value == value) {
				tab.mouseOut();
				foundTab = true;
			}
		}
	};
	
	tabGroups.push(this); // add this TabGroup to the set TabGroups
}

/***************************************
 * Tab class
 * @param tabPageElemId
 * @param tabElemId
 * @param value the value for this Tab option
 ***************************************/
function Tab (tabPageElemId, tabElemId, value) {
	this.tabPageElemId = tabPageElemId;
	this.tabElemId = tabElemId;
	this.value = value;
	
	/**
	 * selects this Tab
	 */
	this.select=function() {
		var tabPageElem = document.getElementById(this.tabPageElemId);
		this.setPageVisible(tabPageElem);
		var tabElem = document.getElementById(tabElemId);
		this.setTabSelected(tabElem);
		this.selected = true;
	};
	
	/**
	 * deselects this Tab
	 */
	this.deselect=function() {
		var tabPageElem = document.getElementById(this.tabPageElemId);
		this.setPageInvisible(tabPageElem);
		var tabElem = document.getElementById(tabElemId);
		this.setTabDeselected(tabElem);
		this.selected = false;
	};
	
	this.mouseOver=function() {
		var tabElem = document.getElementById(tabElemId);
		this.setMouseOver(tabElem);
	};
	
	this.mouseOut=function() {
		// restore the selection to what it was before the mouse over
		if (this.selected) {
			this.select();
		}
		else {
			this.deselect();
		}
	};
}

/**
 * Given the name of an TabGroup, returns that TabGroup
 * @param name the name of the TabGroup to return
 * @return TabGroup the TabGroup with the given name
 */
function getTabGroupByName(name) {
	// go through all of the tab groups
	for (var i = 0; i < tabGroups.length; i++) {
		var tg = tabGroups[i];
		if (tg.name == name) {
			return tg;
		}
	}
}


function onTabClick(value, tabGroupName) {
	var tabGroup = getTabGroupByName(tabGroupName);
	tabGroup.selectTabByValue(value);
}

function onMouseOverTab(value, tabGroupName) {
	var tabGroup = getTabGroupByName(tabGroupName);
	tabGroup.mouseOver(value);
}

function onMouseOutTab(value, tabGroupName) {
	var tabGroup = getTabGroupByName(tabGroupName);
	tabGroup.mouseOut(value);
}


/**
 * called when an option element is clicked
 * selects the given option
 * @param elemId the id of the page element that called this method 
 * @param ogName the name of the OptionGroup that the particular element belongs to
 */
function onOptionClick(elemId, ogName) {
	var optionGroup = getOptionGroupByName(ogName);
	optionGroup.selectOptionByElemId(elemId);			
}
