/**
 * Functions for the <smile:tree>
 * 
 * Tree DOM:
 * 
 * |Root| = <div class=smiletreenode>
 *            [|NodeContent|]
 *          </div>
 * |NodeContent| = 
 *          <div>
 *            <div>
 *              <input name="treeNode_|ID|" label>
 *            </div>
 *          </div>
 *          [HiddenDetailFields]
 *          <div id="treeChildren_|ID|" class="node">
 *            [|NodeContent|]
 *          </div>
 */

var selectedTreeField;

function treeSelectNode(field, onlyExpand) {
	if (selectedTreeField)
		selectedTreeField.className = "";
	
	field.className = "selected";
	var onlyExpand = onlyExpand || selectedTreeField != field; 
	selectedTreeField = field;
	setTreeOptions();
	collapseOrExpand(field.parentNode.parentNode, onlyExpand);
}

function collapseOrExpand(node, onlyExpand) {
	var open = node.nextSibling;
	while (open != null && (!open.className || open.className.indexOf("node") == -1))
		open = open.nextSibling;
	
	if (open.getElementsByTagName("div").length == 0)
	{
		open.style.display = "none";
		return;
	}
	
	if (open == null) return;
	
	var expandIconHolder = node;
	var changeExpandClass = expandIconHolder.className.length != 6; 
	
	if (onlyExpand) {
		if (changeExpandClass)
			expandIconHolder.className = "expand expanded";
		showSlow(open);
		return;
	}
	
	if (open.style.display == "block")
	{
		if (changeExpandClass)
			expandIconHolder.className = "expand collapsed";		
		hideSlow(open);
	}
	else
	{
		if (changeExpandClass)
			expandIconHolder.className = "expand expanded";

		showSlow(open);
	}
}

function showSlow(obj) {
	if (isIE() && !isIE6Plus())
		obj.style.display = "block";
	else
		$("#" + obj.id).show("slow");
}

function hideSlow(obj) {
	if (isIE() && !isIE6Plus())
		obj.style.display = "none";
	else
		$("#" + obj.id).hide("slow");
}

function setTreeOptions() {
	inputs = getTreeDetailFields();
	
	// Put the values in the selects.
	for (var i = 0; i < inputs.length; i++) {
		if (inputs[i].name == "tree_label")
		{
			inputs[i].value = selectedTreeField.value;
			inputs[i].defaultValue = inputs[i].value;
			continue;
		}
		
		inputs[i].value = document.getElementById(selectedTreeField.id + "_" + inputs[i].name).value;
		inputs[i].defaultValue = inputs[i].value; 
	}
}

function getTreeDetailFields() {
	// Find the tree div.
	var treeDiv = selectedTreeField;
	do {
		treeDiv = treeDiv.parentNode;
	} while (treeDiv != null && treeDiv.className != "smiletreeNodes");
	
	// Get the detail div.
	var detailDiv = findPreviousHTMLNode(treeDiv.previousSibling);
	var inputs = new Array();
	if (detailDiv)
	{
		// All input fields
		appendArray(inputs, detailDiv.getElementsByTagName("input"));
		appendArray(inputs, detailDiv.getElementsByTagName("select"));
	}
	
	return inputs;
}

function updateTreeValue(src, event) {
	if (event)
	{
		if (onKey(event, 9, "true"))
		{
			treeSelectNode(src);
			return;
		}
	}
	
	if (selectedTreeField == null)
		return;

	if (src.name.indexOf(".") != -1) {
		document.getElementById("tree_label").value = src.value;
		return;
	}
	if (src.name == "tree_label") {
		selectedTreeField.value = src.value;
		return;
	}
	
	document.getElementById(selectedTreeField.id + "_" + src.name).value = src.value;
}

function getTreeChildDiv() {
	if (selectedTreeField == null)
		return false;
	
	// Get the child div
	var childDiv = selectedTreeField.parentNode.parentNode;
	do {
		childDiv = childDiv.nextSibling;
	} while (childDiv != null && (!childDiv.className || childDiv.className.indexOf("node") == -1));
	
	if (childDiv == null) // panic?
		return false;
	
	return childDiv;
}

function insertTreeNode() {
	var childDiv = getTreeChildDiv();
	if (childDiv === false) return;
	
	// No children yet, add the new child as first node.
	var namePrefix = "";
	if (childDiv.firstChild == null) 
	{
		namePrefix = selectedTreeField.name.substr(0, selectedTreeField.name.length - 6) + ".children[0].";
	}
	else
	{
		var sibling = childDiv.firstChild;
		var count = 0;
		while (sibling != null)
		{
			if (sibling.type && sibling.type == "text")
				count++;
			sibling = sibling.nextSibling;
		}
		
		namePrefix = selectedTreeField.name.substr(0, selectedTreeField.name.length - 6) + ".children["+count+"].";
	}

	var createResult = createNewTreeNode(namePrefix);
	var children = createResult[0];
	var labelInput = createResult[1];
	for (var i = 0; i < children.length; i++)
		childDiv.appendChild(children[i]);
	
	selectedTreeField.parentNode.parentNode.className = "expand expanded";
	treeSelectNode(selectedTreeField, true);
	treeSelectNode(labelInput);
	labelInput.focus();
	rearrangeNumbers();
}

var addedFieldCount = 0;
function createNewTreeNode(namePrefix) {
	var items = new Array();
	var id = "n" + addedFieldCount;
	addedFieldCount++;
	
	var countDiv = document.createElement("div");
	var labelDiv = document.createElement("div");
	var labelInput = document.createElement("input");
	var childDiv = document.createElement("div");
	
	countDiv.appendChild(labelDiv);
	countDiv.className = "expand";
	
	labelDiv.appendChild(labelInput);
	labelDiv.className = "input";
	
	labelDiv.style.backgroundImage = "url(images/icons/numbers/"+(namePrefix.split(".").length-2)+".gif)";
	
	labelInput.name = namePrefix + "label";
	labelInput.id = "treeNode_" + id;
	labelInput.onclick = function() {treeSelectNode(this);};
	labelInput.onkeyup = function(event) {updateTreeValue(this, event);};
	
	childDiv.id = "treeChildren_" + id;
	childDiv.className = "node";
	childDiv.style.display = "none";
	
	items.push(countDiv);
	createTreeHiddenInputs(id, namePrefix, items);
	items.push(childDiv);
	
	var result = new Array();
	result.push(items);
	result.push(labelInput);
	return result;
}

/**
 * Gets all nodes that are related to the selected node.
 * @param target The array in which the nodes will be stored.
 * @return <code>true</code> if there are multiple childnodes.
 */
function getSelectedTreeNodeItems(target) {
	if (selectedTreeField == null) return false;
	
	var nodeDiv = selectedTreeField.parentNode.parentNode;
	target.push(nodeDiv);
	
	// All hidden fields.
	var nextNode = nodeDiv.nextSibling;
	while (nextNode != null && (!nextNode.className || nextNode.className.indexOf("node") == -1))
	{
		target.push(nextNode);
		nextNode = nextNode.nextSibling;
	}
	target.push(nextNode);
	if (target[target.length-1].firstChild != null)
		return true;
	
	return false;
}

function deleteTreeNode() {
	if (selectedTreeField == null) return;
	if (selectedTreeField.parentNode.parentNode.parentNode.className == "smiletreeNodes")
		return;
	
	var items = new Array();
	var hasMore = getSelectedTreeNodeItems(items);
	if (hasMore && !confirm("This item has subitems. Are you sure you want to delete all subitems too?"))
		return;

	updateParentClass(selectedTreeField);
	
	var parent = selectedTreeField.parentNode.parentNode.parentNode;
	for (var i = 0; i < items.length; i++)
	  parent.removeChild(items[i]);
	
	rearrangeNumbers();
}

function updateParentClass(node) {
	var parent = node.parentNode.parentNode.parentNode;
	var prev = parent.previousSibling;
	do
	  prev = prev.previousSibling;
	while (prev != null && (!prev.className || prev.className.indexOf("expand") == -1));

	var items = node.parentNode.parentNode.parentNode.getElementsByTagName("input");
	var count = 0;
	for (var i = 0; i < items.length; i++)
		if (items[i].type != "hidden")
			count++;
	
	prev.className = "expand";
	if (count > 1)
	{
		
		prev.className += " expanded";
	}
}

function moveTreeNodeUp() {
	if (selectedTreeField == null) return;
	var items = new Array();
	getSelectedTreeNodeItems(items);
	if (items.length == 0) return;

	// Get previous input div.
	var prevInput = items[0].previousSibling;
	while (prevInput != null && (!prevInput.className || prevInput.className.indexOf("expand") == -1))
		prevInput = prevInput.previousSibling;
	
	if (prevInput == null) return;
	
	var parent = selectedTreeField.parentNode.parentNode.parentNode;

	for (var i = 0; i < items.length; i++)
	  parent.insertBefore(items[i], prevInput);
	
	rearrangeNumbers();
}

function moveTreeNodeDown() {
	if (selectedTreeField == null) return;
	var items = new Array();
	getSelectedTreeNodeItems(items);
	if (items.length == 0) return;

	// Get previous input div.
	var nextInput = items[items.length-1].nextSibling;
	while (nextInput != null && (!nextInput.className || nextInput.className.indexOf("expand") == -1))
		nextInput = nextInput.nextSibling;
	
	// Last in the list?
	if (nextInput != null)
	{
		// Go even further.
		do
			nextInput = nextInput.nextSibling;
		while (nextInput != null && (!nextInput.className || nextInput.className.indexOf("expand") == -1));
	}
	
	var parent = selectedTreeField.parentNode.parentNode.parentNode;
	if (nextInput == null)
	{
		nextInput = document.createTextNode("");
		parent.appendChild(nextInput);
	}

	for (var i = 0; i < items.length; i++)
	  parent.insertBefore(items[i], nextInput);
	
	rearrangeNumbers();
}

function rearrangeNumbers(root, path) {
	var absRoot = false;
	if (root == null)
	{
		absRoot = true;
		root = document.getElementById("smiletreeNodes");
		if (path && path.indexOf("root") != -1)
			path += "1";
		else
			path = "root";
	}

	var count = -1;
	var inputs = root.getElementsByTagName("input");
	for (var i = 0; i < inputs.length; i++)
	{
		// The elements at this level.
		if ((inputs[i].parentNode == root && inputs[i].type == "hidden") 
	 	 || (inputs[i].parentNode.parentNode.parentNode == root && inputs[i].type != "hidden"))
		{
			if (inputs[i].type != "hidden")
				count++;
			
			var name = inputs[i].name;
			
			var newName = path;
			if (!absRoot)
				newName = path + ".children[" + count + "]";
			inputs[i].name = newName + name.substring(name.lastIndexOf("."));
			
			if (inputs[i].type != "hidden")
			{
				// Get next child div.
				var nextChildDiv = inputs[i].parentNode.parentNode;
				do 
					nextChildDiv = nextChildDiv.nextSibling;
				while (nextChildDiv != null && (!nextChildDiv.className || nextChildDiv.className.indexOf("node") == -1));
				rearrangeNumbers(nextChildDiv, newName);
			}
		}
	}
}

function createTreeHiddenInputs(id, namePrefix, target) {
	var fields = getTreeDetailFields();
	for (var i = 0; i < fields.length; i++) {
		if (fields[i].name == "tree_label")
			continue;
		
		var input = document.createElement("input");
		input.id = "treeNode_" + id + "_" + fields[i].name;
		input.name = namePrefix + fields[i].name;
		input.type = "hidden";
		
		if (fields[i].tagName.toLowerCase() == "select")
			input.value = fields[i].options[0].value;
			
		target.push(input);
	}
}

function appendArray(target, add) {
	for (var i = 0; i < add.length; i++)
		target.push(add[i]);
}