//var ROOT = "";
var ROOT = "/~shaanta";

var DEBUG_MODE = true;

/*
 * General Purpose
 */

// log to javascript console
function log(msg)
{
	setTimeout(function() { throw new Error(msg);}, 0);
}

// simple function that checks whether we're in debug mode or not, and if so will output the specified message
function debug(msg, ret)
{
	if (DEBUG_MODE) log("DEBUG: " + msg);
	return ret;
}

// returns an element for mixed input of element/string id of the element
function get_ele(mixed_ele)
{
	var ele_type = typeof(mixed_ele);
	if (ele_type == 'object') return mixed_ele;
	else if (ele_type == 'string') return document.getElementById(mixed_ele);
	else return null;
}

function get_calling(event)
{
	// FF, Chrome, probably Opera
	if (event.target) return event.target;
	// IE
	else if (event.srcElement) return event.srcElement;
	else
	{
		throw "ERROR: Calling element not found";
		return null;
	}
}

function is_object( mixed_var )
{
	if (mixed_var instanceof Array)
	{
		return false;
	}
	else
	{
		return (mixed_var !== null) && (typeof(mixed_var) == 'object');
	}
}

// if node_type is passed in null, it assumes node_type 1
// if node_type is passed in 0, all elements are returned
function getChildren(mixed_ele, node_type, reverseDirection, numberToReturn)
{
	// ensure something was passed in
	if (mixed_ele == null) return null;
	
	// set node type if not passed in
	if (node_type == null) node_type = 1;
	
	// get the element
	var ele = get_ele(mixed_ele);
	
	// define a return array
	var children = new Array();
	
	// define a counter
	var count = 0;
	
	// look for elements of the specified type
	if (reverseDirection == true)
	{
		for (var i = ele.childNodes.length - 1; i >= 0 && (numberToReturn == null || numberToReturn > count) ; i--) if (node_type == 0 || ele.childNodes[i].nodeType == node_type) children[count++] = ele.childNodes[i];
	}
	else
	{
		for (var i = 0; i < ele.childNodes.length && (numberToReturn == null || numberToReturn > count) ; i++) if (node_type == 0 || ele.childNodes[i].nodeType == node_type) children[count++] = ele.childNodes[i];
	}
	
	return children;
}

function getFirstChild(mixed_ele, node_type)
{
	return getChildren(mixed_ele, node_type, false, 1)[0];
}

function getLastChild(mixed_ele, node_type)
{
	return getChildren(mixed_ele, node_type, true, 1)[0];
}

function childrenCount(mixed_ele, type)
{
	var count = 0;
	
	var ele = get_ele(mixed_ele);
	
	for (var i = 0; i < ele.childNodes.length; i++)
	{
		if (type == null || ele.childNodes[i].nodeType == type) count++;
	}
	
	return count;
}

function clearValues(searchArea)
{
	clearInput('input', searchArea);
	clearInput('textarea', searchArea);
	clearInput('select', searchArea);
}

function clearInput(tagName, searchArea)
{
	var node_list = searchArea.getElementsByTagName(tagName);
	
	for (var i = 0; i < node_list.length; i++)
	{
		var node = node_list[i];
		var type = node.getAttribute('type');
		
		if (tagName == 'textarea' || (tagName == 'input' && (type == 'text' || type == 'password'))) node.value = '';
		else if (tagName == 'select') node.selectedIndex = 0;
	}
}

// expects a html object (not textual id/name/etc.)
function removeParent(event, removeMyParent)
{
	// ensure we have a valid source object
	if (! removeMyParent) removeMyParent = get_calling(event);
	// set the parent object
	var nodeToRemove = removeMyParent.parentNode;
	
	// do the removal
	nodeToRemove.parentNode.removeChild(nodeToRemove);
}

function findSibling(event, search_for, sibling_of)
{
	// make sure we have a valid source object
	if (! sibling_of) sibling_of = get_calling(event);
	// if passed in, ensure we're dealing with an element
	else sibling_of = get_ele(sibling_of);
	
	return findChild(event, search_for, sibling_of.parentNode);
}

function findChild(event, search_for, child_of)
{
	// make sure we have a valid source object
	if (! child_of) child_of = get_calling(event);
	// if passed in, ensure we're dealing with an element
	else child_of = get_ele(child_of);
	
	// get list of siblings
	var children = child_of.childNodes;
	
	var vartype = typeof(search_for);
	if (vartype == "function" || vartype == "object")
	{
		for (var i = 0; i < children.length; i++) if (search_for.test(children[i].name)) return children[i];
	}
	else if (vartype == "string")
	{
		// find our target
		for (var i = 0; i < children.length; i++) if (children[i].name == search_for) return children[i];
	}
	
	// if we returned nothing, return null
	return null;
}

function toggleBlock(mixed_ele)
{
	toggleDisplay(mixed_ele, 'block');
}

function toggleDisplay(mixed_ele, display_type)
{
	var ele = get_ele(mixed_ele);
	
	if (ele.style.display == display_type) ele.style.display = 'none';
	else ele.style.display = display_type;
}


// some quick wrappers for setting values
function name_set_value(target_ele_name, value)
{
	set_value(document.getElementsByName(target_ele_name)[0], value);
}

function id_set_value(id, value)
{
	set_value(get_ele(id), value);
}

function set_value(ele, value)
{
	// make sure ele is set
	if (! ele) return debug("set_value: null ele");
	
	// if an integer value is passed in, and it's a select box, we'll assume we're setting by index
	if (isInteger(value) && ele.tagName == "SELECT")
	{
		ele.selectedIndex = value;
	}
	else
	{
		// TODO: more specialization here
		// if (ele.getAttribute("type") == "CHECKBOX") ele.checked = (bool)value -- etc.
		ele.value = value;
	}
}

// some quick wrappers for setting innerHTML
function name_set_html(target_ele_name, value)
{
	set_html(document.getElementsByName(target_ele_name)[0], value);
}

function id_set_html(id, value)
{
	set_html(get_ele(id), value);
}

function set_html(ele, value)
{
	// make sure ele is set
	if (! ele) return debug("set_html: null ele");
	ele.innerHTML = value;
}

// prevents submission of form on enter keypress
// usage: onkeypress="return noenter()"
function noenter(event)
{
	return !(event && event.keyCode == 13);
}

function increment_form_elements(mixed_ele)
{
	increment_nodes('input', mixed_ele);
	increment_nodes('textarea', mixed_ele);
	increment_nodes('select', mixed_ele);
}

function increment_nodes(tagName, mixed_search)
{
	var node_list = get_ele(mixed_search).getElementsByTagName(tagName);
	
	for (var i = 0; i < node_list.length; i++)
	{
		var node_info = form_array_regex(".+").exec(node_list[i].name);
		if (node_info) node_list[i].name = node_info[1] + "[" + (parseInt(node_info[2]) + 1) + "]";
	}
}

function form_array_regex(ele_name)
{
	var regex_string = '(' + ele_name + ')\\[([0-9]+)\\]';
	return new RegExp(regex_string);
}

function isInteger(s)
{
	return parseInt(s, 10) === s;
}

function mirror(event, destination)
{
	var calling = get_calling(event);
	if (! calling) return;
	
	
	//if (e.keyCode) code = e.keyCode;
	//else if (e.which) code = e.which;
	
	id_set_html(destination, calling.value);
}

/*
 * End General Purpose
 */


/*
 * Clonebox Stuff
 */

function clonebox_add(clonebox_id, max)
{
	// ensure something was passed in
	if (clonebox_id == null) return false;
	
	// get the clonebox element
	var clonebox_ele = get_ele(clonebox_id);
	
	// limit the number of clonebox elements if 'max' variable is present
	if (max && childrenCount(clonebox_id, 1) >= max) return;
	
	// get the source element
	var source_ele = getLastChild(clonebox_ele);
	
	// clone it
	cloned_ele = source_ele.cloneNode(true);
	
	// clear it
	clearValues(cloned_ele);
	
	// increment numerical indexes of form element arrays
	increment_form_elements(cloned_ele);
	
	// append the cloned copy
	clonebox_ele.appendChild(cloned_ele);
	
	// return the cloned element for any other usage
	return cloned_ele;
}

function clonebox_remove(event, clonebox_id)
{
	// set the initial node to remove
	var nodeToRemove = get_calling(event);
	
	// climb up until we find a direct child of the clonebox div
	while (nodeToRemove.parentNode != null && nodeToRemove.parentNode.id != clonebox_id) nodeToRemove = nodeToRemove.parentNode;
	
	// make sure the button calling this is within the clonebox div
	if (nodeToRemove.nodeName == '#document') return debug("clonebox_remove: parent element not found");
	
	// prevent removal of all buttons
	if (childrenCount(clonebox_id, 1) <= 1) return;
	
	// do the removal
	get_ele(clonebox_id).removeChild(nodeToRemove);
}

/*
 * End Clonebox Stuff
 */




/*
 * AJAX Dropdown suggestion box
 */

function suggest_lookup(event, feed, result_target_id, additional_callback)
{
	// get information about the field
	var calling_element = get_calling(event);
	var fieldvalue = calling_element.value;
	
	resultholder = document.getElementById(result_target_id);
	if (! resultholder) return debug("suggest_lookup: null resultholder");
	
	// if there's no input, no need to process
	if (fieldvalue == "")
	{
		resultholder.innerHTML = "";
		return;
	}
	
	// get the key code of the key pressed
	var kc = event.keyCode;
	
	// escape pressed
	if (kc == 27)
	{
		resultholder.innerHTML = "";
		return;
	}
	
	// 16 = shift, 17 = ctrl, 18 = alt, 20 = caps lock, 37 = left arrow, 39 = right arrow, 112-123 = F1-F12, 
	if (kc == 16 || kc == 17 || kc == 18 || kc == 20 || kc == 37 || kc == 39 || (kc >= 112 && kc <= 123)) return;
	
	// up/down arrows, or enter key
	if (kc == 38 || kc == 40 || kc == 13)
	{
		var entries = resultholder.childNodes;
		
		// get selected information
		var sel_index;
		var selected;
		for (i = 0; i < entries.length; i++)
		{
			// check for our selected value
			if (entries[i].nodeType == 8)
			{
				sel_index = i;
				selected = entries[i].nodeValue;
				break;
			}
		}
		
		// if enter button was hit, select the entry that's currently selected
		if (kc == 13)
		{
			if (selected == -1) return;
			
			var value = getFirstChild(entries[selected], 8).nodeValue;
			
			suggest_select(event, calling_element.name, result_target_id, value, additional_callback);
			return;
		}
		
		// controlling up/down of menu
		var offset = 0;
		var increment = 1;
		if (kc == 38)
		{
			offset = entries.length - 2;
			increment = -1;
		}
		
		var prev = -1;
		
		// loop through all entries and deselect the old/select the new
		for (i = 0 + offset; (entries.length - offset) - (i * increment) > 1; i += increment)
		{
			// make sure we have an element tag before continuing
			if (entries[i].nodeType != 1) continue;
			
			if (selected == prev)
			{
				entries[sel_index].nodeValue = i;
				if (prev != -1) entries[prev].className = "";
				entries[i].className = "selected";
			}
			
			prev = i;
		}
		return;
	}
	
	
	// if we've gotten this far, a key was pressed that should result in a new lookup

	var callback = function()
	{
		if (xmlhttp.readyState == 3)
		{
			resultholder.innerHTML = "Loading...";
		}
		else if (xmlhttp.readyState == 4 && xmlhttp.status != 200)
		{
			resultholder.innerHTML = "Error retrieving information.";
		}
		else if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
		{
			if (xmlhttp.responseXML == null)
			{
				resultholder.innerHTML = "Error retrieving data.";
				return false;
			}
			var xmlDoc = xmlhttp.responseXML;
			
			var entries = xmlDoc.documentElement.childNodes;
			
			// variable to contain new content
			var newcontent = "";
			
			// this will store the index of the div (as javascript sees it) of the div that's selected
			newcontent += "\t<!---1-->";
			
			// loop through all entries and output their data
			for (i = 0; i < entries.length; i++)
			{
				if (entries[i].nodeType != 1) continue;
				
				var div_id = "_SELBOX_ENTRY_" + i + "_";
				
				// store <div> tag that holds entry
				newcontent += "\t<div id=\"" + div_id + "\" onclick=\"suggest_select(event, '" + calling_element.name + "', '" + result_target_id + "', '" + additional_callback + "')\">\n";
				
				// get values from data tag
				var data = entries[i].getElementsByTagName("_DATA_")[0].getElementsByTagName("value");
				for (l = 0; l < data.length; l++)
				{
					var value = data[l].childNodes[0].nodeValue;
					newcontent += "\t\t<!--" + value + "-->\n";
				}
				
				// store parts of the entry in spans
				entrynodes = entries[i].childNodes;
				for (j = 0; j < entrynodes.length; j++)
				{
					if (entrynodes[j].nodeType != 1) continue;
					if (entrynodes[j].nodeName == "_DATA_") continue;
					
					var tmp_class = entrynodes[j].nodeName;
					var tmp_content = (entrynodes[j].childNodes[0]) ? entrynodes[j].childNodes[0].nodeValue : "";
					
					newcontent += "\t\t<span class=\"" + tmp_class + "\">" + tmp_content + "</span>\n";
				}
				newcontent += "\t</div>\n";
			}
			
			resultholder.innerHTML = newcontent;
		}
	}
	
	var url = encodeURI(ROOT + "/_assets/feeds/" + feed + ".php?s=" + fieldvalue);
	getContent(url, callback);
}


function suggest_select(event, input_ele_name, result_target_id, additional_callback)
{
	// call additional callback
	if (additional_callback != "undefined") return window[additional_callback](event, input_ele_name, result_target_id);
	
	/**
	 * Default behavior to carry out when a suggest item is selected
	 */
	
	// get data
	var data_array = suggest_get_selected_data(get_calling(event));
	if (! data_array.length > 0) return debug("suggest_select: data_array.length !> 0");
	
	// set the value of the select box
	name_set_value(input_ele_name, data_array[0]);
	
	// clear the pop up display
	id_set_html(result_target_id, "");
}

// returns an array of data elements from suggest option selected
function suggest_get_selected_data(ele)
{
	// climb back up till we find the option's main parent (identified by the first element found with an id)
	while (ele != null && ! ele.id) ele = ele.parentNode;
	if (ele == null) return new Array();
	
	var data_array = new Array();
	var index = 0;
	
	for (var i = 0; i < ele.childNodes.length; i++)
	{
		if (ele.childNodes[i].nodeType != 8) continue;
		data_array[index++] = ele.childNodes[i].nodeValue;
	}
	
	return data_array;
}

/*
 * End AJAX Dropdown suggestion box
 */


/*
 * Shaanta Specific
 */

function shaanta_cat_add(event, container_ele)
{
	//var regexmatch = form_array_regex("cat_custom_desc");
	//log(regexmatch.exec("cat_custom_desc[1256]"));
	
	findChild(event, form_array_regex("cat_custom_desc"), container_ele).checked = false;
	findChild(event, form_array_regex("cat_desc"), container_ele).style.display = "none";
}

function shaanta_cat_callback(event, var1, var2)
{
	// var1 = id of the suggestion box
	// var2 = popup suggest box contents
	
	// get data array
	var data_array = suggest_get_selected_data(get_calling(event));
	if (! data_array.length > 0) return debug("shaanta_cat_callback: data_array.length !> 0");
	
	// clear the input box
	name_set_value(var1, "");
	
	// add a new entry
	shaanta_cat_add(event, clonebox_add("clonebox"));
	
	// get the title select box
	var cat_title_ele = findChild(event, form_array_regex("cat_title"), getLastChild("clonebox"));
	
	// set the value of the selectbox in the new entry
	set_value(cat_title_ele, data_array[0]);
	
	// call the load stuff
	shaanta_load_cat(cat_title_ele);
	
	// clear the pop-up suggest box
	id_set_html(var2, "");
}

function shaanta_toggle_cat_desc(event, source_ele)
{
	// check and set the visiblity of the description box
	var cat_desc = findSibling(event, form_array_regex("cat_desc"));
	if (cat_desc == null) return debug("shaanta_toggle_cat_desc: unable to find cat_desc");
	
	// if it's showing, hide it
	if (cat_desc.style.display == "block")
	{
		cat_desc.style.display = "none";
	}
	// in all other cases, show the box
	else
	{
		cat_desc.style.display = "block";
		
		// if we're showing the box, load the contents
		shaanta_load_cat(event, source_ele);
	}
}

// loads category information and shoves it into sibling cat_desc[] textarea
function shaanta_load_cat(event, source_ele)
{
	if (! source_ele) return debug("shaanta_load_cat: null source_ele");
	
	// make sure we're looking at the right element (in case function is called from an element other than the select box
	var cat_ele;
	cat_ele = findSibling(event, form_array_regex("cat_title"), source_ele);
	if (! cat_ele) return debug("shaanta_load_cat: null cat_ele");
	var cat_value = cat_ele.value;
	
	// now get the description element
	var desc_ele = findSibling(event, form_array_regex("cat_desc"), cat_ele);
	
	var callback = function()
	{
		if (xmlhttp.readyState == 3)
		{
			desc_ele.value = "Loading...";
		}
		else if (xmlhttp.readyState == 4 && xmlhttp.status != 200)
		{
			desc_ele.value = "Error retrieving information.";
		}
		else if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
		{
			var response = xmlhttp.responseText;
			desc_ele.value = response;
		}
	}

	var url = encodeURI(ROOT + "/_assets/feeds/cats_descs.php?s=" + cat_value);
	getContent(url, callback);
	
}

function shaanta_busspectitle_callback(event, var1, var2)
{
	// var1 = id of the suggestion box
	// var2 = popup suggest box contents
	
	var data_array = suggest_get_selected_data(get_calling(event));
	if (! data_array.length > 0) return debug("shaanta_busspectitle_callback: data_array.length !> 0");
	
	// clear the input box
	name_set_value(var1, "");
	
	// clear the pop-up suggest box
	id_set_html(var2, "");
	
	// set the value of the selectbox in the new entry
	name_set_value("entity_title", data_array[0]);
	
	// set the select box value for business/specialist type
	if (data_array[1] == "business") name_set_value("entity_type", "Business");
	else if (data_array[1] == "specialist") name_set_value("entity_type", "Specialist");
}

/*
 * End Shaanta Specific
 */



