var tree = new Tree();

/** 
 * tree class
 */
function Tree()
{
	var allNodes = new Array();
	var eventListener = new Array();
	var writeTop = 0;


	/** 
	 * initialzie
	 * @param inPanel : set div tag
	 */
	this.Initialize = function(inPanel)
	{
		panel = inPanel;

	}
	
	/** 
	 * get panel
	 * @return panel
	 */
	this.getPanel = function()
	{
		return panel;
	}

	/** 
	 * get all node array
	 * @return node array
	 */
	this.getAllNodes = function()
	{
		return allNodes;
	}

	/** 
	 * redraw
	 */
	this.redraw = function()
	{
		var tag = "";

		writeTop = 0;
		for (var i = 0; i < allNodes.length; i++)
		{
			if (allNodes[i].getParent() == null)
			{
				tag += allNodes[i].writeTag();
			}
		}

		panel.innerHTML = tag;
	}

	/** 
	 * expand tree 
	 * @param nodeIndex : node index (sequence)
	 */
	this.onExpandClick = function(nodeIndex)
	{
		allNodes[nodeIndex].expand();
		
		this.redraw();
	}
	
	/** 
	 * collapse event
	 * @param nodeIndex : node index (sequence)
	 */
	this.onCollapseClick = function(nodeIndex)
	{
		allNodes[nodeIndex].collapse();

		this.redraw();
	}

	/** 
	 * check event
	 * @param nodeIndex :  node index (sequence)
	 * @param checkBox : check state
	 */
	this.onCheckClick = function(nodeIndex, checked)
	{
		this.checkAndRedraw(nodeIndex, checked);

		var i = 0;
		for(i = 0; i < eventListener.length; i++)
		{
			eventListener[i].onCheckChanged(allNodes[nodeIndex]);
		}
	}

	/** 
	 * check event
	 * @param nodeIndex :  node index (sequence)
	 * @param checkBox : check state
	 */
	this.checkAndRedraw = function(nodeIndex, checked)
	{
		allNodes[nodeIndex].setCheckFamily(checked);

		this.redraw();
	}

	/** 
	 * add node 
	 * @param nodeName : node name
	 * @param parentNode : parent node
	 * @param layerIcon : layer icon url
	 * @param legendPath : legend image url
	 * @param userData : user data (this version using layer object)
	 * @return created node
	 */
	this.addNode = function(nodeName, subLabel, parentNode, layerIcon, legendPath, userData)
	{
		var node = new Node(parentNode, nodeName, subLabel, layerIcon, legendPath);

		if (parentNode != null)
		{
			parentNode.addChild(node);
		}

		if (userData != null)
		{
			node.setUserData(userData);
		}

		return node;
	}

	/** 
	 * get write start position
	 * @return write start position
	 */
	this.getWriteTop = function()
	{
		return writeTop;
	}

	/** 
	 * set write start position
	 * @param wirte start position
	 */
	this.setWriteTop = function(newValue)
	{
		writeTop = newValue;
	}

	/** 
	 * event set
	 * @param listener listener class
	 */
	this.addEventListener = function(listener)
	{
		eventListener.push(listener);
	}
}


/** 
 * node class
 * @param inParent parent node
 * @param inLabel node label
 * @param inLayerIcon layer icon url
 * @param inLegendPath legend image url
 */
function Node(inParent, inLabel, inSubLabel, inLayerIcon, inLegendPath)
{
	var label = inLabel;
	var subLabel = inSubLabel;
	var parent = inParent;
	var expanded = true;
	var layerIcon = inLayerIcon;
	var legendPath = inLegendPath;

	var children = new Array();
	var check = true;
	var indent;
	
	var nodeIndex = tree.getAllNodes().length;

	var userData;

	tree.getAllNodes()[nodeIndex] = this;

	if (inParent == null)
	{
		indent = 0;
	}
	else
	{
		indent = inParent.getIndent() + 1;
	}

	/** 
	 * write tag
	 * @return writed tag
	 */
	this.writeTag = function()
	{
		var tag = "";
		var childIndex;
		var checkParent = parent;
		var parentLine = "";

		tag = "<div style='position: absolute; top: " + tree.getWriteTop() + "px; left:0px'>";
		
		while (checkParent != null)
		{
			if (!checkParent.isLastChild())
			{
				parentLine = "<img src=\"MapForm/img/treeLine1.gif\">" + parentLine;
			}
			else
			{
				parentLine = "<img src=\"MapForm/img/treeSpace.gif\">" + parentLine;
			}
			checkParent = checkParent.getParent();
		}
		tag += parentLine;
		if (children.length > 0)
		{
			if (expanded)
			{
				tag += "<img src=\"MapForm/img/collapse.gif\" onclick=\"tree.onCollapseClick(" + nodeIndex +")\">";
			}
			else
			{
				tag += "<img src=\"MapForm/img/expand.gif\" onclick=\"tree.onExpandClick(" + nodeIndex +")\">";
			}
		}
		else
		{
			if (this.isLastChild())
			{
				tag += "<img src=\"MapForm/img/treeLine3.gif\">";
			}
			else
			{
				tag += "<img src=\"MapForm/img/treeLine2.gif\">";
			}
		}
		tag += "<input id=\"" + label + "\" type=\"checkbox\" style = \"CURSOR:pointer;\" ";
		if (check)
		{
			tag += " checked ";
		}
		tag += "onclick=\"tree.onCheckClick(" + nodeIndex + ", this.checked)\">";
		
		if (children.length > 0)
		{
			tag += "<img src='MapForm/img/treeFolder.gif' width=16 height=16>";
		}
		else
		{
//			tag += "<img src='MapForm/img/treeLayer.gif'>";
			tag += "<img src='" + layerIcon + "' width=16 height=16 onmouseover =\"mapImage.ShowHanreiWin('"+ legendPath +"', this)\" onmouseout =\"mapImage.UnShowHanreiWin()\">";
		}
		tag += label;
		if (subLabel != null)
		{
			tag += "<font color='Navy'>" + subLabel + "</font>";
		}

		tree.setWriteTop(tree.getWriteTop() + 19);
		tag += "</div>";

		// write child tag.
		if (expanded)
		{
			for (childIndex = 0; childIndex < children.length; childIndex++)
			{
				tag += children[childIndex].writeTag();
			}
		}

		return tag;
	}

	/** 
	 * get parent node
	 * @return parent node
	 */
	this.getParent = function()
	{
		return parent;
	}

	/** 
	 * get expand state
	 * @return expanded state
	 */
	this.isExpanded = function()
	{
		return expanded;
	}

	/** 
	 * expand child
	 */
	this.expand = function()
	{
		expanded = true;
	}

	/** 
	 * collapse child
	 */
	this.collapse = function()
	{
		expanded = false;
	}

	/** 
	 * get label
	 * @return label
	 */
	this.getLabel = function()
	{
		return label;
	}

	/** 
	 * get indent
	 * @return indent
	 */
	this.getIndent = function()
	{
		return indent;
	}

	/** 
	 * get children
	 * @return children

	 */
	this.getChildren = function()
	{
		return children;
	}

	/** 
	 * add child
	 * @param child node
	 */
	this.addChild = function(node)
	{
		children.push(node);
	}

	/** 
	 * get check state
	 * @return check state
	 */
	this.isChecked = function()
	{
		return check;
	}

	/** 
	 * set check state
	 * @param newValue check state
	 */
	this.setCheck = function(newValue)
	{
/* 初期表示の際(特定のレイヤだけ表示等)に問題あり 
		if (check == newValue)
		{
			return;
		}
*/		
		check = newValue;
	
		if (parent != null)
		{
			// set parent check state
			if (newValue == true)
			{
				parent.setCheck(true);
			}
			else
			{
				// uncheck parent when all brothers are not checked.
				var i;
				var allUnChecked = true;
				var brothers = parent.getChildren();
				
				for (i = 0; i < brothers.length; i++)
				{
					if (brothers[i].isChecked())
					{
						allUnChecked = false;
						break;
					}
				}
				if (allUnChecked)
				{
					parent.setCheck(false);
				}
			}
		}
	}

	/** 
	 * set check state with children
	 * @param newValue check state
	 */
	this.setCheckFamily = function(newValue)
	{
		if (check == newValue)
		{
			return;
		}
	
		this.setCheck(newValue);
		
		var i;
		for (i = 0; i < children.length; i++)
		{
			children[i].setCheckFamily(newValue);
		}
	}

	/** 
	 * get user data
	 * @return newValue user data
	 */
	this.getUserData = function()
	{
		return userData;
	}

	/** 
	 * set user data
	 * @param newValue user data
	 */
	this.setUserData = function(newValue)
	{
		userData = newValue;
	}

	/**
	 * is last child
	 */
	this.isLastChild = function()
	{
		if (parent != null)
		{
			var brothers = parent.getChildren();

			return (brothers[brothers.length - 1] == this);
		}
		else
		{
			return true;
		}
	}	
}


