var last_hightlighted = null;
var last_highlighted_key = null;

function TreeItem(title, url, icon, onclick, priority, debug_only)
{
	this.Title = title;
	this.Url = url;
	this.Rendered = false;
	this.Displayed = false;
	this.Level = 0;
	this.Icon = icon;
	this.Onclick = onclick;
	this.Priority = isset(priority) ? priority : false;
	this.debugOnly = isset(debug_only) ? debug_only : false;
	this.Children = false;
}

TreeItem.prototype.isFolder = function()
{
	return typeof(this.folderClick) == 'function';
}

TreeItem.prototype.isContainer = function()
{
	return this.isFolder() && this.Container;
}

TreeItem.prototype.isLoaded = function()
{
	if (!this.isFolder()) {
		return false;
	}

	return (this.LateLoadURL && this.Loaded) || !this.LateLoadURL;
}

TreeItem.prototype.Render = function(before, force)
{
	if (!this.Rendered || force) {
		if (!isset(before)) {before = null}

		tr = document.createElement('tr');
		this.ParentElement.insertBefore(tr, before);
		if (!this.Displayed) { tr.style.display = 'none' }
		td = document.createElement('td');
		td.TreeElement = this;
		tr.appendChild(td);

		this.appendLevel(td);
		if (this.ParentFolder != null) this.appendNodeImage(td);
		this.appendIcon(td);
		this.appendLink(td);

		this.Tr = tr;
		this.Rendered = true;
//		alert(this.Tr.innerHTML)
	}
}

TreeItem.prototype.remove = function()
{
	var p = this.Tr.parentNode;
	p.removeChild(this.Tr);
}

TreeItem.prototype.appendLevel = function(td)
{
	for (var i=0; i < this.Level; i++)
	{
		img = document.createElement('img');
		img.style.width = '16px';
		img.style.height = '22px';
		img.src = TREE_ICONS_PATH+'/ftv2blank.gif';
		img.style.verticalAlign = 'middle';
		td.appendChild(img);
	}
}

TreeItem.prototype.getNodeImage = function(is_last)
{
	return is_last ? TREE_ICONS_PATH+'/ftv2lastnode.gif' : TREE_ICONS_PATH+'/ftv2node.gif';
}

TreeItem.prototype.appendNodeImage = function(td)
{
	img = document.createElement('img');
	img.style.width = '16px';
	img.style.height = '22px';
	img.src = this.getNodeImage();
	img.style.verticalAlign = 'middle';
	td.appendChild(img);
}

TreeItem.prototype.appendIcon = function (td)
{
	img = document.createElement('img');
//	img.style.width = '24px';
//	img.style.height = '22px';
	if (this.Icon.indexOf('http://') != -1) {
		img.src = this.Icon;
	}
	else {
		img.src = this.Icon;
	}
	img.style.verticalAlign = 'middle';
	td.appendChild(img);
}

TreeItem.prototype.appendLink = function (td)
{
	var $node_text = document.createElement('span');
	$node_text.innerHTML = this.Title;
	if (TREE_SHOW_PRIORITY && this.Priority !== false) {
		$node_text.innerHTML += '<span class="priority"><sup>' + this.Priority + '</sup></span>';
	}

	link = document.createElement('a');
	link.nodeValue = this.Title;

	if (this.debugOnly) {
		link.className = 'debug-only-item';
	}

	link.href = this.Url;
	link.target = 'main';
	link.appendChild($node_text);

	link.treeItem = this;
	//addEvent(link, 'click',

	link.onclick =
			function(ev) {
				var e = is.ie ? window.event : ev;

				res = true;
				if (isset(this.treeItem.Onclick)) {
					res = eval(this.treeItem.Onclick);
				}
				if (!res) { // if we need to cancel onclick action
					if (is.ie) {
						window.event.cancelBubble = true;
						window.event.returnValue = false;
					} else {
						ev.preventDefault();
						ev.stopPropagation();
					}
					return res;
				}
				else {
					// ensures, that click is made before AJAX request will be sent
					var $res_type = Object.prototype.toString.call(res);

					if ((res === true) || ($res_type == '[object Object]')) {
						// in case of "true" is returned, used in catalog
						// in case of object (tree node) is returned, used in advanced view
						if (this.treeItem.isContainer()) {
							if (this.treeItem.isLoaded()) {
								this.treeItem.ContainerClicked = false;
								this.href = this.treeItem.locateFirstItem().Url;
								getFrame(link.target).location.href = this.href;
							}
							else {
								this.treeItem.ContainerClicked = true;
							}
						}
						else {
							getFrame(link.target).location.href = this.href;
						}
					}

					if (!this.treeItem.Expanded && this.treeItem.isFolder()) {
						if (this.treeItem.folderClick());
					}

					if ($res_type == '[object Object]') {
						// highlight returned tree node instead of clicked one
						res.highLight(false); // don't expand such node
					}
					else {
						this.treeItem.highLight();
					}

					return false;
				}
			}

	td.appendChild(link);

	/*
	if (this.LateLoadURL) {
		var span = document.createElement('span');
		span.innerHTML = '&nbsp;Reload';
		span.treeItem = this;
		span.onclick = function(ev) {
			this.treeItem.reload();
		}
		td.appendChild(span);
	}
	*/
}

TreeItem.prototype.display = function()
{
	this.Tr.style.display = ''; // is.ie ? 'block' : 'table-row';
	this.Displayed = true;

	var do_sub =  TreeManager.isExpanded(this.Key);
	if (this.Children && do_sub && !this.Expanding) {
		this.expand();
	}

	if (this.ParentFolder != null && !this.ParentFolder.Expanded) {
		this.ParentFolder.expand();
	}
}

TreeItem.prototype.hide = function()
{
	this.Tr.style.display = 'none';
	this.Displayed = false;
}

TreeItem.prototype.highLight = function($auto_expand)
{
	if ($auto_expand === undefined) {
		$auto_expand = true;
	}

	if (last_hightlighted) {
		last_hightlighted.Tr.className = '';
	}

	if (this.Children && this.Children.length > 0 && this.isContainer()) {
		if (!this.Expanded && $auto_expand) {
			this.expand();
		}

		this.Children[0].highLight($auto_expand);
		return;
	}

	this.Tr.className = "highlighted";
	last_hightlighted = this;
	last_highlighted_key = this.Key;
	if (!this.Expanded && $auto_expand) {
		this.expand();
	}
}

TreeItem.prototype.expand = function() {
	this.display();
}

TreeItem.prototype.collapse = function() { this.hide() }

TreeItem.prototype.updateLastNodes = function(is_last, lines_pattern)
{
	if (!isset(is_last)) is_last = true;
	if (!isset(this.Tr)) return;
	if (!isset(lines_pattern)) { var lines_pattern = new Array() }

	imgs = this.Tr.getElementsByTagName('img');
	found = false;
	for (var i=0; i<imgs.length; i++)
	{
		the_img = imgs.item(i);
		if (in_array(i, lines_pattern) && the_img.src.indexOf('ftv2blank.gif') != -1) {
			the_img.src = TREE_ICONS_PATH+'/ftv2vertline.gif';
		}
		if (this.isNodeImage(the_img))
		{
			found = true;
			break;
		}
	}
	if (found) {
		the_img.src = this.getNodeImage(is_last);
	}
	this.isLast = is_last;
	return lines_pattern;
}

TreeItem.prototype.isNodeImage = function(img)
{
	return (
					img.src.indexOf('ftv2node.gif') != -1 ||
					img.src.indexOf('ftv2lastnode.gif') != -1
				 )

}

TreeItem.prototype.locateLastItem = function()
{
	return this;
}

TreeItem.prototype.locateItemByURL = function(url)
{
	if (this.Url == url) return this;
	return false;
}

TreeItem.prototype.locateItemByKey = function(key)
{
	if (this.Key == key) return this;
	return false;
}

TreeItem.prototype.reload = function()
{
}

/* FOLDER */

function TreeFolder(parent_id, title, url, icon, late_load_url, onclick, priority, container, debug_only)
{
	var render = false;
	if (isset(parent_id)) {
		this.ParentElement = document.getElementById(parent_id);
		render = true;
	}
	else {

	}

	this.Title = title;
	this.Url = url;
	this.Rendered = false;
	this.Displayed = false;
	this.Expanded = false;
	this.Level = 0;
	this.Id = 0;
	this.Tr = null;
	this.Icon = icon;
	this.LateLoadURL = isset(late_load_url) ? late_load_url : false;
	this.Loaded = false;
	this.Onclick = onclick;
	this.Priority = isset(priority) ? priority : false;
	this.debugOnly = isset(debug_only) ? debug_only : false;
	this.Container = isset(container) ? parseInt(container) : false;
	this.ContainerClicked = false;

	this.Children = new Array();
	this.ChildIndex = 0;
	this.Reloading = false;

	if (render) {
		this.Expanded = true;
		this.Displayed = true;
		this.Render();
		this.expand();
	}
}

TreeFolder.prototype = new TreeItem;

TreeFolder.prototype.locateLastItem = function()
{
	if (this.Children.length == 0) return this;

	for (var i=0; i<this.Children.length; i++)
	{
		last_item = this.Children[i].locateLastItem()
	}
	return last_item;
}

TreeFolder.prototype.locateFirstItem = function()
{
	var $folder_node = this;
	while ($folder_node.isContainer() && $folder_node.Children.length > 0) {
		$folder_node = $folder_node.Children[0];
	}

	return $folder_node;
}

TreeFolder.prototype.locateItemByURL = function(url, with_late_load)
{
	last_item = false;

	if (this.Url == url && ( (with_late_load && this.LateLoadURL) || !with_late_load) ) {
		return this;
	}

	for (var i=0; i<this.Children.length; i++)
	{
		last_item = this.Children[i].locateItemByURL(url, with_late_load)
		if (last_item) return last_item;
	}
	return last_item;
}

TreeFolder.prototype.locateItemByKey = function(key)
{
	last_item = false;
	if (this.Key == key) {
		return this;
	}

	for (var i=0; i<this.Children.length; i++)
	{
		last_item = this.Children[i].locateItemByKey(key)
		if (last_item) return last_item;
	}
	return last_item;
}

TreeFolder.prototype.locateTopItem = function()
{
	if (this.ParentFolder == null) return this;
	return this.ParentFolder.locateTopItem();
}

TreeFolder.prototype.AddItem = function(an_item, render, display) {
	an_item.ParentElement = this.ParentElement;
	an_item.Level = this.ParentFolder != null ? this.Level + 1 : 0;
	an_item.ParentFolder = this;

	last_item = this.locateLastItem();
	this.Children.push(an_item);
	an_item.Id = this.Children.length;
	an_item.Render(last_item.Tr.nextSibling);

	var keys = new Array()
	var tmp = an_item;
	keys.push(tmp.Level + '_' + tmp.Id);
	while (tmp.ParentFolder) {
		tmp = tmp.ParentFolder
		keys.push(tmp.Level + '_' + tmp.Id);
	}
	keys = keys.reverse();
	key_str = keys.join('-');
	an_item.Key = key_str;

	if (this.Expanded)
	{
		an_item.display();
	}

	return an_item;
}

TreeFolder.prototype.AddFromXML = function(xml, render)
{
//	start = new Date();
	if (!isset(render)) render = true;
	doc = getDocumentFromXML(xml);
	this.LastFolder = this;
	this.ProcessXMLNode(doc, render);
//	end = new Date();
	this.locateTopItem().updateLastNodes();
//	alert('AddFromXML took: '+(end - start))
}

TreeFolder.prototype.ProcessXMLNode = function(node, render)
{
	if (!isset(render)) render = true;
	if (!isset(this.LastFolder)) this.LastFolder = this;
	for (var i=0; i<node.childNodes.length; i++)
	{
		child = node.childNodes.item(i);
		if (child.tagName == 'folder') {
			var backupLastFolder = this.LastFolder;
			this.LastFolder = this.LastFolder.AddItem(new TreeFolder(null, child.getAttribute('name'), child.getAttribute('href'), child.getAttribute('icon'), child.getAttribute('load_url'), child.getAttribute('onclick'), child.getAttribute('priority'), child.getAttribute('container'), child.getAttribute('debug_only')), render);
			if (child.hasChildNodes) {
				this.ProcessXMLNode(child);
			}
			this.LastFolder = backupLastFolder;
		}
		else if (child.tagName == 'item') {
			this.LastFolder.AddItem(new TreeItem(child.firstChild.nodeValue, child.getAttribute('href'), child.getAttribute('icon'), child.getAttribute('onclick'), child.getAttribute('priority'), child.getAttribute('debug_only')), render)
		}
		else if (child.tagName == 'tree') {
			this.LastFolder = this;
			this.ProcessXMLNode(child);
		}
	}
}

TreeFolder.prototype.getNodeImage = function(is_last)
{
	if (is_last) {
		return this.Expanded ? TREE_ICONS_PATH+'/ftv2mlastnode.gif' : TREE_ICONS_PATH+'/ftv2plastnode.gif';
	}
	else {
		return this.Expanded ? TREE_ICONS_PATH+'/ftv2mnode.gif' : TREE_ICONS_PATH+'/ftv2pnode.gif';
	}
}

TreeFolder.prototype.appendNodeImage = function(td, is_last)
{
	img = document.createElement('img');
	img.style.width = '16px';
	img.style.height = '22px';
	img.src = this.getNodeImage(is_last);
	img.style.cursor = 'hand';
	img.style.cursor = 'pointer';
	img.style.verticalAlign = 'middle';
	img.onclick = function() { this.parentNode.TreeElement.folderClick(this)	}
	this.Img = img;
	td.appendChild(img);
}

TreeFolder.prototype.updateLastNodes = function(is_last, lines_pattern)
{
	if (!isset(is_last)) is_last = true;
	if (!isset(lines_pattern)) { var lines_pattern = new Array() }
	if (!is_last && !in_array(this.Level, lines_pattern)) {	lines_pattern.push(this.Level) }

	lines_pattern = TreeItem.prototype.updateLastNodes.apply(this, new Array(is_last, lines_pattern))

	for (var i=0; i<this.Children.length; i++)
	{
		lines_pattern = this.Children[i].updateLastNodes((i+1) == this.Children.length, lines_pattern)
	}
	lines_pattern[array_search(this.Level, lines_pattern)] = -1;
	return lines_pattern;
}

TreeFolder.prototype.isNodeImage = function(img)
{
	return (
					img.src.indexOf('ftv2mlastnode.gif') != -1 ||
					img.src.indexOf('ftv2plastnode.gif') != -1 ||
					img.src.indexOf('ftv2mnode.gif') != -1 ||
					img.src.indexOf('ftv2pnode.gif') != -1
				 )

}

TreeFolder.prototype.folderClick = function(img)
{
	if (this.Expanded) {
		this.collapse();
	}
	else {
		this.expand();
	}
}

TreeFolder.prototype.remove = function()
{
	this.removeChildren();
	var p = this.Tr.parentNode;
	p.removeChild(this.Tr);
}

TreeFolder.prototype.removeChildren = function()
{
	for (var i=0; i<this.Children.length; i++) {
		this.Children[i].remove();
	}
	this.Children = new Array();
}

TreeFolder.prototype.successCallback = function ($request, $params, $object) {
	/*if ($params == 'reload') {
		$object.removeChildren();
	}*/

	$object.removeChildren(); // will also remove "Loading ..." node

	$object.Loaded = true;
	$object.ProcessXMLNode($request.responseXML);
	$object.Render();
	$object.locateTopItem().updateLastNodes();
	$object.expand();

	if (last_highlighted_key) {
		var fld = $object.locateItemByKey(last_highlighted_key)
		if (fld) {
			if (fld.ParentFolder.ContainerClicked) {
				$('a:first', fld.Tr).click();
			}
			else {
				fld.highLight();
			}
		}
	}

	$object.Reloading = false;
}

TreeFolder.prototype.reload = function()
{
	if (this.Reloading) {
		return ;
	}

	this.Reloading = true;

	// add "Loading ..." node
	this.AddLoadingNode();

	// sending request to receive items
	Request.headers['Content-type'] = 'text/xml';
	Request.makeRequest(this.LateLoadURL, false, '', this.successCallback, this.errorCallback, 'reload', this);
}

TreeFolder.prototype.errorCallback = function($request, $params, $object) {
	alert('AJAX ERROR: ' + Request.getErrorHtml($request));

	$object.Reloading = false;
}

TreeFolder.prototype.expand = function(mode)
{
	if (this.Expanding) {
		return;
	}
	this.Expanding = true;

	if (!isset(mode)) mode = 0;
	this.display();
	if (mode == 0 || this.Expanded ) {
		for (var i=0; i<this.Children.length; i++)
		{
			this.Children[i].expand(mode+1);
		}
	}
	if (mode == 0) {
		if (this.LateLoadURL && !this.Loaded) {
			// add "Loading ..." node
			this.AddLoadingNode();

			// sending request to receive items
			Request.headers['Content-type'] = 'text/xml';
			Request.makeRequest(this.LateLoadURL, false, '', this.successCallback, this.errorCallback, '', this);
		}
		this.Expanded = true;
		TreeManager.markStatus(this.Key, 1)
		if (isset(this.Img)) {
			this.Img.src = this.getNodeImage(this.isLast);
		}
	}
	this.Expanding = false;
}

TreeFolder.prototype.AddLoadingNode = function() {
	// remove all current children (including "Loading ...")
	this.removeChildren();

	// add "Loading ..." node
	var $loading_item = this.AddItem(new TreeItem(TREE_LOADING_NODE.text, '#', TREE_LOADING_NODE.icon, '', 1), true);
	this.locateTopItem().updateLastNodes();
	$loading_item.display();
}

TreeFolder.prototype.collapse = function(mode)
{
	if (!isset(mode)) mode = 0;
	for (var i=0; i<this.Children.length; i++)
	{
		this.Children[i].collapse(mode+1);
		this.Children[i].hide();
	}
	if (mode == 0) {
		this.Expanded = false;
		TreeManager.markStatus(this.Key, 0)
		if (isset(this.Img)) {
			this.Img.src = this.getNodeImage(this.isLast);
		}
	}
}


function TreeManager() {}

TreeManager.ExpandStatus = {};

TreeManager.markStatus = function(id, status)
{
	this.ExpandStatus[id] = status;
	if (!status) {
		for (var i in this.ExpandStatus) {
			if (i.indexOf(id) == 0) { // if i starts with the same as id, meaning it is its child node
				this.ExpandStatus[i] = 0;
			}
		}
	}
	TreeManager.saveStatus()
}

TreeManager.isExpanded = function(id)
{
	return (this.ExpandStatus[id] == 1);
}

TreeManager.saveStatus = function ()
{
	var cookieString = new Array();

	for (var i in this.ExpandStatus) {
		if (this.ExpandStatus[i] == 1) {
			cookieString.push(i);
		}
	}
	document.cookie = 'TreeExpandStatus=' + cookieString.join(':');
}

TreeManager.loadStatus = function () {
	var $tree_status = getCookie('TreeExpandStatus');
	if (!$tree_status) {
		return ;
	}

	$tree_status = $tree_status.split(':');
	for (var $i = 0; $i < $tree_status.length; $i++) {
		this.ExpandStatus[$tree_status[$i]] = true;
	}

//	print_pre(this.ExpandStatus);
}

TreeManager.loadStatus();