var g_treeOptions = new Array();

function createTree(parent, hasChildren, expanded, lastChild, options, _id, name, icon)
{
    var parser = new TemplateParser();
    if (typeof icon == "undefined" || !icon)
        icon = "icon_folder";
        
    parser.assign("foldername", name);
    parser.assign("icon", icon);
    parser.assign("hasChildren", hasChildren ? "1" : "0");
    parser.assign("expanded",    hasChildren && expanded ? "1" : "0");
    parser.assign("lastChild",   lastChild ? "1" : "0");
    parser.assign("inputBox", options.inputBox ? "1" : "0");
    parser.assign("id", _id);
    var text = parser.parse("treeItem.tpl");
    parent.innerHTML += text;
    
    return parent.lastChild ? parent.lastChild.firstChild.childNodes[1].childNodes[1] : null;
}

function tree_getId(obj)
{
    return obj.firstChild.firstChild.firstChild.firstChild.innerHTML.replace(/&amp;/, "&");
}

function tree_getName(obj)
{
    return tree_getNameObj(obj).innerHTML.replace(/&amp;/, "&");
}

function tree_getNameObj(obj)
{
	var childNodes = obj.firstChild.firstChild.childNodes[1].childNodes;
    return childNodes[childNodes.length-1];
}

function tree_getChildrenNode(obj)
{
    return obj.firstChild.childNodes[1].childNodes[1];
}

function tree_getParentNode(obj)
{
    var node = obj.parentNode.parentNode.parentNode.parentNode;
    
    return node.nodeName == "TABLE" ? node : null;
}

function tree_getRootNode(obj)
{
    node = obj;
    while(node != null)
    {
        rootNode = node;
        node = tree_getParentNode(node);
    }
    
    return rootNode;
}

function tree_getOptions(obj)
{
    var rootNode = tree_getRootNode(obj);
    var id = rootNode.parentNode.id;
    if (!g_treeOptions[id])
    {
    	g_treeOptions[id] = new Object();
    	g_treeOptions[id].checkChildren = true;
    	g_treeOptions[id].treeRoot = obj;
    	g_treeOptions[id].dontDragBelow = Array();
    }
    return g_treeOptions[id];
}

function tree_getCheckedIds(obj)
{
    var ret = new Array();
    var checked = tree_getCheck(obj);
    var options = tree_getOptions(obj);
    if (checked == "full")
    {
        ret.push(tree_getId(obj));
    }
    
    if (checked == "half" || !options.checkChildren)
    {
        // add children
        var childrenNodes = tree_getChildrenNode(obj).childNodes;
        var i;
        for(i=0; i<childrenNodes.length; i++)
        {
            ret = ret.concat(tree_getCheckedIds(childrenNodes[i]));
        }
    }
    return ret;
}

function tree_findObj(root, id)
{
    if (tree_getId(root) == id)
    {
        return root;
    }
    else
    {
        var childrenNodes = tree_getChildrenNode(root).childNodes;
        var i;
        for(i=0; i<childrenNodes.length; i++)
        {
            var ret = tree_findObj(childrenNodes[i], id);
            if (ret)
            {
                return ret;
            } 
        }
    }
    
    return null;
}

function tree_getSelected(obj, previous)
{
    if (typeof previous == "undefined")
    	previous = false;
    	
    var options = tree_getOptions(obj);
    
    var item = previous ? options.prevSelectedItem : options.selectedItem;

    if (!item)
        return null;
    else
    {
        return tree_getId(item.parentNode.parentNode.parentNode.parentNode);
    }
}

function tree_getSelectedObj(obj, previous)
{
    if (typeof previous == "undefined")
    	previous = false;
    	
    var options = tree_getOptions(obj);
    
    var item = previous ? options.prevSelectedItem : options.selectedItem;
	
	return item ? item.parentNode.parentNode.parentNode.parentNode : null;
}

function tree_getSpan(obj)
{
    var span = obj.firstChild.firstChild.childNodes[1].firstChild;
    while(span && span.nodeName != "SPAN")
    {
        span = span.nextSibling;
    }
	
	return span;
}

function tree_setSelected(root, id, _skipEventHandler)
{
    var obj = tree_findObj(root, id);
    var skipEventHandler = typeof _skipEventHandler != "undefined" ? _skipEventHandler : true;
    
	if (obj)
    {
        var span = tree_getSpan(obj);
        if (span)
            tree_onSelectItem(span, true);
                    
        if (!skipEventHandler)
        {
        	var options = tree_getOptions(root);
        	if (options.onSelectItem)
        		options.onSelectItem(obj)
        }
        tree_ensureVisible(root, id);   	
    }
}

function tree_isExpandable(tableNode)
{
    var obj = tableNode.firstChild.firstChild.firstChild;
    return obj.style.backgroundImage.indexOf("plus") != -1 || obj.style.backgroundImage.indexOf("minus") != -1;
}

function tree_isExpanded(tableNode)
{
    var obj = tableNode.firstChild.childNodes[1];
    return obj.style.display != 'none';
	
}

function tree_setExpanded(tableNode, expanded)
{
    var obj = tableNode.firstChild.firstChild.firstChild;
    var lastChild = obj.style.backgroundImage.indexOf("_end.gif") != -1;
    
    var baseUrl = /url\((.*)images\/treeControl/;
    baseUrl = baseUrl.exec(obj.style.backgroundImage)[1];
    obj.style.backgroundImage = !expanded ? "url(" + baseUrl + "images/treeControl/plus" + (lastChild ? "_end.gif)" : ".gif)") : "url(" + baseUrl + "images/treeControl/minus" + (lastChild ? "_end.gif)" : ".gif)");
    obj.parentNode.nextSibling.style.display = expanded ? '' : 'none';
    
    var childrenNode = tree_getChildrenNode(tableNode);
	var options = tree_getOptions(tableNode);
    if (childrenNode.innerHTML == "")
    {
        // children still need to be build 
        var _id = tree_getId(tableNode);
        if (options.localTree)
            buildLocalTree(childrenNode, options, options.itemType, _id, true);
        else
            buildRemoteTree(childrenNode, options, options.itemType, _id, true);
        if (tree_getCheck(tableNode) == "full")
            tree_setCheck(tableNode, "full");
    }
    
    
	if (options.onSize)
    {
    	options.onSize(tableNode);
    }
}

function tree_onToggleExpand(obj)
{
    var expanded = obj.parentNode.nextSibling.style.display == 'none';
    tree_setExpanded(obj.parentNode.parentNode.parentNode, expanded);
}

function tree_setCheck(obj, type, skipParentCheck)
{
    if (!type)
    {
        type = "full";
    }
    
    var childrenNodes = tree_getChildrenNode(obj);
    if (!childrenNodes)
    	childrenNodes = Array();
    else
    	childrenNodes = childrenNodes.childNodes;
    	
    var i;
    
	var options = tree_getOptions(obj);
	if (options.checkChildren)
	{
	    if (type == "full" || type == "empty")
	    {
	        for(i=0; i<childrenNodes.length; i++)
	        {
	            tree_setCheck(childrenNodes[i], type, true);
	        }
	    }
	    else
	    {
	        // check if type "half" should not actually be "empty" or "full"
	        var allEmpty = true;
	        i=0;
	        while(i<childrenNodes.length && (allEmpty))
	        {
	            var checked = tree_getCheck(childrenNodes[i]);
	            if (checked != "empty")
	            {
	                allEmpty = false;
	            }
	            i++;
	        }
	        
	        if (allEmpty)
	        {
	            type = "empty";
	        }
	    }
	}

    var img = obj.firstChild.firstChild.childNodes[1].firstChild;
    
    var re = /^(.*)images\/treeControl\/checkbox_/;
    var url = re.exec(img.src)[1];
    img.src = url + "images/treeControl/checkbox_" + type + ".gif";
    
 	if (options.checkChildren)
	{
	    var parent = tree_getParentNode(obj);
	    if (parent && !skipParentCheck)
	    {
	        tree_setCheck(parent, "half");
	    }
	}
}

function tree_getCheck(obj)
{
    var src = obj.firstChild.firstChild.childNodes[1].firstChild.src;
    var re=/checkbox_([^\.]+).gif$/;
    var matches = src.match(re);
    return matches ? matches[1] : "empty";
}

function tree_onInputBox(obj)
{
    var table = obj.parentNode.parentNode.parentNode.parentNode;
    var check = tree_getCheck(table) != "full" ? "full" : "empty";
    
    tree_setCheck(table, check);
}

var g_treeSelectedItem = null;

function tree_onDragDone(dragOptions)
{
	var options = dragOptions.treeOptions;
	options.dragging = false;
	if (options.dragDest)
	{
		var span = tree_getSpan(options.dragDest);
		setOpacity(span, 100);
		span.className = "";
	}
	var span = tree_getSpan(options.dragSrc);
	setOpacity(span, 100);

	options.dragSrc.style.display = "";
	if ((!options.dragDest || options.dragDest == options.dragSrc)) 
	{
		if (!options.skipEventHandler && options.onSelectItem)
			options.onSelectItem(options.dragSrc);
		else if (options.onRename)
    	{
    		tree_rename(options.dragSrc);
    	}
	}
	
	if (options.onDragDone && options.dragDest && options.dragDest != options.dragSrc)
		options.onDragDone(options.treeRoot, options.dragSrc, options.dragDest);
	
	options.dragSrc = null;
	options.dragDest = null;
}

function tree_onDragMouseMove(options, event, x, y)
{
	var objects = Array();
	var x = x - getScreenPosX(options.treeRoot.offsetParent);
	var y = y - getScreenPosY(options.treeRoot.offsetParent);
	getObjectsFromPoint(x, y, objects, options.treeRoot);
	var lastTree = null;
	var lastTD = null;
	for(var i=objects.length-1; i >=0 && !lastTree; i--)
	{
		if (objects[i].nodeName == "TABLE")
		{
			var id = tree_getId(objects[i]);
			if (id)
			{
				lastTree = objects[i];
				lastTD = lastTree.firstChild.firstChild.firstChild;	
			}
		}
	}
	
	var below = false;
	for(i=0; i<options.dontDragBelow.length && !below; i++)
	{
		below = dom_isDescendant(lastTree, options.dontDragBelow[i]);
	}
	
	if (lastTree && lastTree != options.dragDest && lastTree != options.dragSrc && 
		(!below))
   	{
	   	if (options.dragDest)
	   	{
	   		var span = tree_getSpan(options.dragDest);
	   		span.className = "";
	   	}
	   	options.dragDest = lastTree;
	   	var span = tree_getSpan(options.dragDest);
	   	span.className = "selected";
   	}
   	else if (lastTree == options.dragSrc)
   	{
   		if (options.dragDest)
   		{
   			var span = tree_getSpan(options.dragDest);
	   		span.className = "";
   		}
   		options.dragDest = null;
   	}
   	
   	// check if above '+'-sign
   	var abovePlus = lastTD && lastTD.style.backgroundImage.search(/plus/) != -1;
   	if (abovePlus && lastTD != options.abovePlus)
   	{
   		options.abovePlus = lastTD;
   		options.abovePlusTimer = window.setTimeout(function()
   		{
   			if (options.abovePlus == lastTD)
   			{
   				tree_onToggleExpand(lastTD);
			}
   		}, 1500);
   	}
   	else if (!abovePlus && options.abovePlus)
   	{
   		options.abovePlus = null;
   		window.clearTimeout(options.abovePlusTimer);
   	}
}

function tree_onSelectItem(obj, skipEventHandler, event)
{
	var tableNode = obj.parentNode.parentNode.parentNode.parentNode;
    var options = tree_getOptions(tableNode);
    if (options.dragging)
    	return;
    
    if (options.selectedItem)
    {
        options.selectedItem.className = "";
    }
    
    obj.className = "selected";
    
    if (options.prevSelectedItem != options.selectedItem)
    {
	    options.prevSelectedItem = options.selectedItem;
    }
    
    var result = true;
    
    options.skipEventHandler = skipEventHandler;
    
    if (!skipEventHandler && options.allowDrag)
    {
	    var dragOptions = new Object();
	    
	    dragOptions.onDragDone = tree_onDragDone;
	    options.dragging = true;
	    options.dragSrc = tableNode;
	    var span = tree_getSpan(tableNode);
	    setOpacity(span, 50);
	    dragOptions.treeOptions = options;
	    dragOptions.onMouseMove = function(event, x, y)
	    {
	    	tree_onDragMouseMove(options, event, x, y);
	    }
	    
	    options.dontDragBelow = Array(tableNode);
	    result = drag_start(obj, event, dragOptions);
    }
    else if (!skipEventHandler && !options.allowDrag && options.onSelectItem)
    {
    	options.onSelectItem(tableNode);
    }

    if (options.selectedItem == obj)
    {
    	skipEventHandler = true;
    }

    options.selectedItem = obj;

    options.skipEventHandler = skipEventHandler;

    return result;
}

function tree_ensureVisible(obj, id, prefix)
{
    var childrenNode = tree_getChildrenNode(obj);
    var childrenNodes = childrenNode.childNodes;
    if (tree_isExpandable(obj)) 
    {
        tree_setExpanded(obj, true);
    }
    if (typeof prefix == "undefined" || prefix == null)
        prefix = tree_getId(obj);
        
    if (prefix.length >= 1 && prefix.charAt(prefix.length-1) != '/')
        prefix += "/";

    var re = /^\/?([^\/]+)(?:\/(.*))?$/;
    if (id.match(re))
    {
        var i;
        var done = false;
        for(i=0; i<childrenNodes.length && !done; i++)
        {
            if (tree_getId(childrenNodes[i]) == prefix + RegExp.$1)
            {
                done = tree_ensureVisible(childrenNodes[i], RegExp.$2);
            }
        }
        return done;
    }
    
    return false;
}

function tree_getPath(obj)
{
	var parent = tree_getParentNode(obj);
	var path = "";
	if (parent)
		path = tree_getPath(parent);
	
	path += "/" + tree_getName(obj);
	
	return path;
}

function tree_onkey(obj, event)
{
	var charcode = event.keyCode ? event.keyCode : event.which;

	var newSelect = null;
    var options = tree_getOptions(obj);
    var item = options.selectedItem;
    //window.status = charcode;
    
	var currentSelected = item ? item.parentNode.parentNode.parentNode.parentNode : options.treeRoot;
	var childrenNode = tree_getChildrenNode(currentSelected);
	var expanded = childrenNode && childrenNode.childNodes.length > 0 && tree_isExpanded(currentSelected);
	var parentNode = tree_getParentNode(currentSelected);
	
	switch(charcode)
	{
	    case 46:
	    	// delete
	    	if (options.onDelete)
	    		options.onDelete(currentSelected);
	    	break;
	    case 113:
	    	// F2
	    	if (options.onRename)
		    	tree_rename(currentSelected);
	    	break;
	    	
	    case 37:
	    	// go left
	    	if (expanded)
	    	{
	    		tree_setExpanded(currentSelected, false)
	    	}
	    	else
	    	{
	    		newSelect = parentNode;
	    	}
	    	break;
	    	
	    case 39:
	    	// go right
	    	if (!expanded && tree_isExpandable(currentSelected))
	    	{
	    		tree_setExpanded(currentSelected, true);
	    	}
	    	else if (childrenNode && childrenNode.childNodes.length > 0)
	    	{
	    		newSelect = childrenNode.childNodes[0];
	    	}
	    	break;
	    
	    case 38:
			// go up
			newSelect = currentSelected.previousSibling;
			
			if (newSelect)
			do
			{
				var childrenNode = tree_getChildrenNode(newSelect);
				
				var expanded = tree_isExpanded(newSelect);
				if (childrenNode.lastChild && expanded)
					newSelect = childrenNode.lastChild;
			}
			while(childrenNode.lastChild && expanded);
			
			if (!newSelect)
				newSelect = tree_getParentNode(currentSelected);
			
			break;
		case 40:
			// go down
			if (expanded)
			{
				newSelect = tree_getChildrenNode(currentSelected);
				newSelect = newSelect && newSelect.childNodes.length > 0 ? newSelect.childNodes[0] : null;
			}
			else
			{
				newSelect = currentSelected.nextSibling;
			}
			
			while(!newSelect && parentNode)
			{
				if (parentNode.nextSibling)
					newSelect = parentNode.nextSibling;
				else
				{
					parentNode = tree_getParentNode(parentNode);
				}
			}
			
			break;
	}
	
	if (newSelect && newSelect.nodeName == "TABLE")
	{
		tree_setSelected(obj, tree_getId(newSelect), false, event);
		return false;
	}
	
	return true;
}

function tree_onkeyPress(event)
{
	var charcode = event.keyCode ? event.keyCode : event.which;

	switch(charcode)
	{
	    case 46:
	    case 113:
	    case 37:
	    case 39:
	    case 38:
		case 40:
			return false;
			break;
		default:
			return true;
	}
}

function tree_hideRename(obj)
{
	var options = tree_getOptions(obj);

	options.renameInput.parentNode.removeChild(options.renameInput);
	options.outerClick.parentNode.removeChild(options.outerClick);
	
	var treeRoot = tree_getRootNode(obj);
	window.setTimeout(function() {treeRoot.parentNode.focus();}, 250);
}

function tree_rename(_obj, id)
{
	var obj = typeof id != "undefined" ? tree_findObj(_obj, id) : _obj;
	var span = tree_getSpan(obj);
	var options = tree_getOptions(obj);
	
	var outerClick = createTotalDiv("black", 20);
	options.outerClick = outerClick;
	outerClick.onclick = function() { tree_hideRename(obj); }
	outerClick.style.zOffset = "-1";
	document.body.appendChild(outerClick);

	var newInput = document.createElement("input");
	newInput.style.border = "1px black solid";
	
	newInput.style.position = "absolute";
	newInput.style.left = getScreenPosX(span) + "px";
	newInput.style.top = getScreenPosY(span) + "px";
	newInput.style.width = "auto";
	newInput.style.zOffset = "1";
	newInput.value = span.innerHTML;
	newInput.onkeyup = function(_evt) 
	{  
		var event = _evt ? _evt : window.event;
		var charCode = event.keyCode ? event.keyCode : event.which;
		if (charCode == 27)
		{
			tree_hideRename(obj);
		}
		else if (charCode == 13)
		{
			var newName = newInput.value;
			tree_hideRename(obj);
			if (options.onRename)
				options.onRename(obj, newName);
				
			span.innerHTML = newName;
			return false;
		}
		
		return true;
	}
	document.body.appendChild(newInput);
	newInput.focus();
	newInput.select();
	options.renameInput = newInput;
}

function tree_setName(obj, name)
{
	var span = tree_getSpan(obj);
	span.innerHTML = name;
}

function tree_getNextSibling(treeItem)
{
	return treeItem.nextSibling;	
}

function tree_getPreviousSibling(treeItem)
{
	return treeItem.previousSibling;	
}

function tree_getDragDestObject(treeRoot)
{
	var ret = new Object();
	ret.treeRoot = treeRoot;
	
	var options = tree_getOptions(treeRoot);
	
	var oldSelected = null;
	ret.onStart = function(notBelow)
	{
		oldSelected = tree_getSelectedObj(treeRoot);
		var span = tree_getSpan(oldSelected);
		span.className = "";
		var objs = Array();
		for(var i=0; i<notBelow.length; i++)
		{
			objs.push(tree_findObj(treeRoot, notBelow[i]));
		}
		options.dontDragBelow = objs;
	}
	
	ret.onFinish = function()
	{
		var span;
		
		if (options.dragDest)
		{
			span = tree_getSpan(options.dragDest);
			
			span.className = "";
		}
		span = tree_getSpan(oldSelected);
		span.className = "selected";
	}
	
	ret.onMouseMove = function(event, x, y)
	{
		tree_onDragMouseMove(options, event, x, y);
		return options.dragDest ? tree_getId(options.dragDest) : null;
	}
	
	return ret;
}
