var hidden_elements = new Array();

function update_quantity(selection_box, elt_id)
{
//	Logger.info("update_quantity() with selection_box " + selection_box + ", elt_id " + elt_id);

	form_elt = document.getElementById(elt_id);
	
	if(!form_elt)
		return;
	
	if(selection_box.checked)
	{
		if(form_elt.value <= 1)
			form_elt.value = 1;
	}
	else
		form_elt.value = '0';
}

function select_all_subs(checkbox_elt, parent_slid)
{
//	Logger.info("select_all_subs() with checkbox_elt " + checkbox_elt + ", parent_slid " + parent_slid);

	//Only activate with a select on 'all'; dont' deactivate on un-select
	if(!checkbox_elt.checked)
		return;
		
	subs = children_of[parent_slid];
	parent_cid = category_of[parent_slid];
	
	for(var i in subs)
	{
		if(typeof(subs[i]) == 'function')
			continue;
			
		slid = subs[i];
		
		form_elt_id = 'category_' + parent_cid + '_selection_' + slid;
		form_elt = document.getElementById(form_elt_id);
		
		if(form_elt != null)
			form_elt.checked = true;
	
		//Is there a quantity box for this checkbox? If so, update its value.
		quantity_elt_id = 'category_' + parent_cid + '_selection_' + slid + '_quantity';
		quantity_elt = document.getElementById(quantity_elt_id);
		if(quantity_elt)
			update_quantity(form_elt, quantity_elt_id);
	}
}

function unselect_all(checkbox_elt, cid, slid)
{
//	Logger.info("unselect_all() with checkbox_elt " + checkbox_elt + ", cid " + cid + ", slid " + slid);
	
	if(!checkbox_elt.checked)
	{
		all_elt_id = 'category_' + cid + '_selection_' + slid + '_all';
		all_elt = document.getElementById(all_elt_id);
		
		if(all_elt != null)
			all_elt.checked = false;
	}
}

function activate_selection_control(elt_id)
{
//	Logger.info("activate_selection_control() with elt_id " + elt_id);
	
	control_elt = document.getElementById(elt_id)
	if(control_elt != null)
		control_elt.checked = true;
}

//Examine the control elements for all selections in every required category.
//If a required category does not have at least one checked control element,
//return false. Else return true.
function check_required_categories()
{
	Logger.info("check_required_categories()");

	did_alert = false;

	//Examine every required category in this step
	for(var i in required_categories)
	{
		if(typeof(required_categories[i]) == 'function')
			continue;
		
		this_cid = required_categories[i];
		
		found_a_selection = false;
		found_a_selection_for = new Array();
				
		//Examine every selection in this required category
		for(var j in selections_in[this_cid])
		{
			if(typeof(selections_in[this_cid][j]) == 'function')
				continue;
			
			this_slid = selections_in[this_cid][j];
			
			//Determine the control element ID associated with this selection. This will vary
			//by the category's selection_type and whether the selection is a sub-selection or 
			//a parent.
			switch(selection_type_of[this_cid])
			{
				case 'single':
					control_elt_id = 'category_' + this_cid + '_selection_' + this_slid;
					break;
				
				case 'single_sub':
					//Is this a child selection?
					if(parent_of[this_slid] != null)
						control_elt_id = 'category_' + this_cid + '_selection_' + parent_of[this_slid] + '_sub_' + this_slid;
					else
						control_elt_id = 'category_' + this_cid + '_selection_' + this_slid;
					break;
				
				case 'multi':
					control_elt_id = 'category_' + this_cid + '_selection_' + this_slid;
					break;
			}
			
			//Get the control element
			control_elt = document.getElementById(control_elt_id);
			
			//Not all selections have controls - those with max_quantity 0, for instance.			
			if(control_elt == null)
				continue;
				
			Logger.info("Checking control element " + control_elt_id + ", which is " + control_elt);
//			debugArray(control_elt);
			
			//If the control element is a "hidden" element (which would be the case in display() with multi-type categories),
			//it doesn't need to have "checked" - just a value of 1.

			//Is it checked, or is it hidden with a non-zero value?
			if(control_elt.checked || (control_elt.type == "hidden" && control_elt.value))
			{
				if(selection_type_of[this_cid] == 'single' || selection_type_of[this_cid] == 'multi')
					found_a_selection = true;
				
				//single_sub type categories need to have a valid selection for EACH parent
				//selection in the category.
				else
				{	
					if(parent_of[this_slid] != null)
						found_a_selection_for[parent_of[this_slid]] = true;
					else
						found_a_selection_for[this_slid] = true;
				}
			}
		}
		
		single_sub_missing_selection = false;
		
		//Make sure that single_sub categories have a valid selection for each parent.
		//This will require us to re-examine every parent selection element and check to be
		//sure that in the previous iteration we found some selection for that parent.
		if(selection_type_of[this_cid] != 'single' && selection_type_of[this_cid] != 'multi')
		{
			for(var j in selections_in[this_cid])
			{
				if(typeof(selections_in[this_cid][j]) == 'function')
					continue;
					
				this_slid = selections_in[this_cid][j];
				
				//Is this a parent selection?
				if(parent_of[this_slid] == null)
				{
					display_elt_id = 'selection_' + this_slid;
					
					Logger.info("Checking for a value for parent_elt " + display_elt_id);
					
					cur_elt_hidden = hidden_elements[display_elt_id];
					cur_elt = document.getElementById(display_elt_id);
				
					Logger.info(display_elt_id + " is " + cur_elt);
				
					if(cur_elt != null && !found_a_selection_for[this_slid] && !cur_elt_hidden)
						single_sub_missing_selection = true;
				}
			}
			
			found_a_selection = !single_sub_missing_selection;
		}
		
		
		//If we did not find a checked element among the control elements for the selections
		//in this required category, return false.
		if(!found_a_selection)
		{
			if(!did_alert)
			{
				category_name = category_names[this_cid];
				alert("Please make selection in \"" + category_name + "\" before going on to the next step.");
			}
			
			did_alert = true;
			return false;
		}
	}
	
	//Got here? No required category was without a checked control element. Return true.
	return true;
}

//Sets the 'display' property of elt_id to 'display_value' to an appropriate value indicated by the 
//dependency charts for slid and its parent element. If the element indicates hiding, the function
//returns false. Otherwise the function returns true.
//elt_id: The ID of the element to show or hide
//slid: the ID of the selection whose dependencies should govern whether elt_id is shown or hidden
//display_value: (optional) one of 'block' or 'inline'
function show_by_dependency(elt_id, slid, display_value)
{
//	Logger.info("show_by_dependency with elt_id " + elt_id + ", slid " + slid + ", display_value " + display_value);

	//Some elements may not be rendered by the display template (for instance, if their pre-step
	//dependencies have not been met). In this case, bail out here.
	elt = document.getElementById(elt_id)
	if(!elt)
		return;

	my_dependencies = dependencies[slid];
	my_parent_dependencies = parent_dependencies[slid];
	
	if(display_value == null)
		display_value = 'block';
	
	show_elt = true;
	
	//First examine the element's own dependencies
	for(var cid in my_dependencies)
	{
		if(typeof(my_dependencies[cid]) == 'function')
			continue;
			
		required_slid = my_dependencies[cid];
		required_cid = category_of[required_slid];
		selection_type = selection_type_of[required_cid];
		
		//If there is no requirement for this category, go on with life.
		if(!required_slid)
			continue;
		
//		Logger.info("I require selection " + required_slid + " in category " + required_cid);
		
		//Is the selection type of the category in question something other than single_sub?
		//OR is the element that is required a parent element?
		//In either case, the format of the determining control element is category_#_selection_#
		if(selection_type != "single_sub" || typeof(children_of[required_slid]) == 'object')
			selection_elt_id = 'category_' + cid + '_selection_' + required_slid;
			
		//Inverse: The category selection type is single_sub AND the required element is a child element.
		//The format will be category_#_selection_#_sub_#
		else
		{
			parent_slid = parent_of[required_slid];
			selection_elt_id = 'category_' + cid + '_selection_' + parent_slid + '_sub_' + required_slid;
		}
		
//		Logger.info("examining selection_elt " + selection_elt_id);
		
		selection_elt = document.getElementById(selection_elt_id);
		
		if(!selection_elt || !selection_elt.checked)
			show_elt = false;
	}
	
	//Now examine the parent's dependencies, if there is a parent
	if(my_parent_dependencies != null && typeof(my_parent_dependencies) == 'object')
	{
		for(var cid in my_parent_dependencies)
		{
			if(typeof(my_parent_dependencies[cid]) == 'function')
				continue;
				
			required_slid = my_parent_dependencies[cid];
			required_cid = category_of[required_slid];
			selection_type = selection_type_of[required_cid];
			
			//If there is no requirement for this category, go on with life.
			if(!required_slid)
				continue;
			
			//Is the selection type of the category in question something other than single_sub?
			//OR is the element that is required a parent element?
			//In either case, the format of the determining control element is category_#_selection_#
			if(selection_type != "single_sub" || typeof(children_of[required_slid]) == 'object')
				selection_elt_id = 'category_' + cid + '_selection_' + required_slid;
				
			//Inverse: The category selection type is single_sub AND the required element is a child element.
			//The format will be category_#_selection_#_sub_#
			else
			{
				parent_slid = parent_of[required_slid];
				selection_elt_id = 'category_' + cid + '_selection_' + parent_slid + '_sub_' + required_slid;
			}
			
			selection_elt = document.getElementById(selection_elt_id);
			
			if(selection_elt == null)
				continue;
			
			if(!selection_elt.checked)
				show_elt = false;
		}
	}
	
	//Show the element
	if(show_elt)
	{
//		Logger.info("Trying to display " + elt_id);
	
		setStyleById(elt_id, 'display', display_value);
		hidden_elements[elt_id] = false;
		return true;
	}
	
	//Hide the element
	else
	{
//		Logger.info("Trying to hide " + elt_id);
	
		//Find the control element associated with this slid, so we can un-check it.
		my_parent_slid = parent_of[slid];
		my_category = category_of[slid];
		my_selection_type = selection_type_of[my_category];
	
		//Is the selection type of this element's category something other than single_sub?
		//OR is this element a parent element?
		//In either case, the format of this selection's control element is category_#_selection_#
		if(my_selection_type != "single_sub" || typeof(children_of[slid]) == 'object')
			my_selection_elt_id = 'category_' + my_category + '_selection_' + slid;
			
		//Inverse: The category selection type is single_sub AND this element is a child element.
		//The format will be category_#_selection_#_sub_#
		else
			my_selection_elt_id = 'category_' + my_category + '_selection_' + my_parent_slid + '_sub_' + slid;
	
		//Un-check the control, if there is one.
		my_selection_elt = document.getElementById(my_selection_elt_id);
		if(my_selection_elt != null && typeof(my_selection_elt) == 'object')
			my_selection_elt.checked = false;
		
		setStyleById(elt_id, 'display', 'none');
		hidden_elements[elt_id] = true;
		
		return false;
	}
}

//Invokes show_by_dependency on all children of a display.
//If the category's selection type is 'multi', also shows or hides the 'all' checkbox
//as appropriate.
//cid: The ID of the category whose child selections should be updated
function update_category_selection_display(cid)
{
//	Logger.info("update_category_selection_display() with cid " + cid);

	my_children = selections_in[cid];
	
	visible_count = 0;
	
	for(var i in my_children)
	{
		if(typeof(my_children[i]) == 'function')
			continue
	
		child_slid = my_children[i];
		child_elt_id = 'selection_' + child_slid;
		result = show_by_dependency(child_elt_id, child_slid, 'block');

		if(result)
			visible_count++;
	}
	
	if(selection_type_of[cid] == 'multi')
	{
		all_elt_id = 'category_' + cid + '_select_all_div';

		if(visible_count > 1)
		{
//			Logger.info("Trying to set " + all_elt_id + " to display block");

			all_elt_element = document.getElementById(all_elt_id);
			if(all_elt_element != null)
			{
				setStyleById(all_elt_id, 'display', 'block');
				hidden_elements[all_elt_id] = false;
			}
		}
		else
		{
//			Logger.info("Trying to set " + all_elt_id + " to display none");

			all_elt_element = document.getElementById(all_elt_id);
			if(all_elt_element != null)
			{
				setStyleById(all_elt_id, 'display', 'none');
				hidden_elements[all_elt_id] = true;
			}
		}
	}
}

//Invokes update_category_selection_display() on all cids
function update_all_categories()
{
//	Logger.info("update_all_categories()");

	//We use selection_type_of for a slightly different purpose here - just to get
	//a list of all the CIDs in involved in this step.
	for(var cid in selection_type_of)
	{
		if(typeof(selection_type_of[cid]) == 'function')
			continue;
		
		update_category_selection_display(cid);
	}
}

function debugArray(arr)
{
	if(!Logger.info)
		return;

	for(var j in arr)
	{
		if(typeof(arr[j]) == 'function')
			continue;
	
		Logger.info(j + " => " + arr[j]);
	}
}