/**
 * 
 * @author Hahm Myung Sun (hms1475@gmail.com)
 *
 * Copyright (c) 2011 JinoTech (http://www.jinotech.com) 
 * Licensed under the LGPL v3.0 license (http://www.gnu.org/licenses/lgpl.html).
 */

jTableLayout = function (map){
	this.map = map;
	this.HGAP = 0; 
	this.VGAP = 0;
	
	this.xSize = 0;
	this.ySize = 0;
	
	// 가운데가 보이게...
	var work = this.map.work;
	work.scrollLeft = Math.round( (work.scrollWidth - work.offsetWidth)/2 );
	work.scrollTop = Math.round( (work.scrollHeight - work.offsetHeight)/2 );
}

jTableLayout.prototype.type= "jTableLayout";

jTableLayout.prototype.layoutNode = function(/*jNode*/ node) {
	var x = 0;
	var wgap = node.wgap;
	if (isNaN(wgap)) wgap = 0;
	if(node.isRootNode()) {
		y = 0;
	} else {
		y = parseFloat(node.parent.body.getBBox().width) ;
	}

	this.placeNode(node,x , node.vshift);
	
	// ArrowLink Update
	node.connectArrowLink();
	//나를 가르키는 arrowlink들에 대해 connect를 다시 한다.
	var alinks = jMap.getArrowLinks(node);
	for(var i = 0; i < alinks.length; i++) {
		alinks[i].draw();
	}
	
	if(node.folded == "false" || node.folded == false) {
		//var children = node.getUnChildren();
		var children = node.getChildren();
		if (children != null && children.length > 0) {
			for (var i = 0; i < children.length; i++) {
				this.layoutNode(children[i]);
			}
		}
	}
}

jTableLayout.prototype.layout = function(/*boolean*/ holdSelected) {
	var selected = this.map.selectedNodes.getLastElement();
	
	holdSelected = holdSelected &&
	 (selected != null && selected.getLocation().x != 0 && selected.getLocation().y != 0);
	 
	var rootNode = this.getRoot();
	var oldRootX = rootNode.getLocation().x;
	var oldRootY = rootNode.getLocation().y;
	if(holdSelected) {
		oldRootX = selected.getLocation().x;
	}
	
	this.resizeMap(rootNode.treeWidth, rootNode.treeHeight);
	this.layoutNode(this.getRoot());
}

jTableLayout.prototype.updateTreeHeightsAndRelativeYOfDescendantsAndAncestors = function(/*jNode*/ node) {

	this.updateTreeHeightsAndRelativeYOfDescendants(node);
	if (! node.isRootNode()) {
       this.updateTreeHeightsAndRelativeYOfAncestors(node.getParent());
	}
}

jTableLayout.prototype.updateTreeHeightsAndRelativeYOfAncestors = function(/*jNode*/ node) {
	this.updateTreeGeometry(node);

	if (!node.isRootNode()) {
		this.updateTreeHeightsAndRelativeYOfAncestors(node.getParent());
	}
}

jTableLayout.prototype.updateTreeHeightsAndRelativeYOfWholeMap = function() {
	this.updateTreeHeightsAndRelativeYOfDescendants(this.getRoot()); 
	this.layout(false);
}

jTableLayout.prototype.updateTreeHeightsAndRelativeYOfDescendants = function(/*jNode*/ node) {
	var children = node.getUnChildren();
	if(children != null && children.length > 0){
		for(var i=0; i<children.length; i++) {
			this.updateTreeHeightsAndRelativeYOfDescendants(children[i]);
		}
	}
	
	this.updateTreeGeometry(node);
}

//////////////////////////////////////
//var parent=this.getRoot();
jTableLayout.prototype.maxDepth = function(node) {
	var children = node.getUnChildren();
	if(children == null || children.length == 0) {
		return node.getDepth();
	}	
	var mDepth = 0;
	for(var i = 0; i < children.length; i++) {
		mDepth = Math.max(mDepth,
						this.maxDepth(children[i])
			);
	}

	return mDepth;
//	var aaaa=this.getRoot();
//	this.map.createNodeWithCtrl(aaaa,"")
}

jTableLayout.prototype.makeNode = function(node,maxDepth) {
	var children = node.getUnChildren();
	if(children == null || children.length == 0) {
		if (node.getDepth()<maxDepth){
			this.map.createNodeWithCtrl(node,"");
//			alert("ok")
		}
	}
	for(var i = 0; i < children.length; i++) {
		this.makeNode(children[i],maxDepth);
	}
}

/////////////////////////////////////

jTableLayout.prototype.updateTreeGeometry = function(/*jNode*/ node) {

	var children = node.getUnChildren();
	var depth=node.getDepth();
	
	// width
	var treeWidth = this.calcTreeWidth(node, children);
	node.setTreeWidth(treeWidth);

	// height
	var treeHeight = this.calcTreeHeight(node, children);
	node.setTreeHeight(treeHeight);	
	
	// node height
	var treeWidth1 = this.calcTreeWidth1(node);
	
	//size가장 넓은 길이에 맞추는거
	if (node.isRootNode()) {
		node.setSize(this.getRoot().getSize().width, this.getRoot().getSize().height);}
	else {node.setSize(treeWidth1,treeHeight);}
	
	var calcWidth = function(node, widths, index) {					
		var width = node.body.getBBox().width;
		if(!widths[index]) widths[index] = 0;
		widths[index] = (width > widths[index])? width : widths[index];
		
		if(node.getChildren().length > 0) {
			var children = node.getChildren();
			index++;
			for(var i = 0; i < children.length; i++) {
				calcWidth(children[i], widths, index);						
			}
		}		
	}
	var maxWidth = [];
	calcWidth(jMap.getRootNode(), maxWidth, 0);
	
	if (depth==0) {node.setSize(this.getRoot().getSize().width, this.getRoot().getSize().height);}
	else{
//		if (depth!=1){
//			var parentHeight=node.getParent().getSize().height;
//			if(treeHeight<parentHeight){
//				var nnn = node.getParent().getChildren().length;
//				treeHeight=parentHeight/nnn;						
//			}
//		}
		node.setSize(maxWidth[depth],treeHeight);
	}
	
	
//	//가장위에있는노드에 맞추는거(없다면 width=150)
//	var root= this.getRoot();
//	var twidth = 0;
//	var aaa="root";
//	var fd=0;
//	while(eval(aaa)){
//		aaa+=".getChildren()[0]";
//		fd++
//	}
//	
//	if (depth==0) {
//		node.setSize(this.getRoot().getSize().width, this.getRoot().getSize().height);}
//	else if(depth>fd){node.setSize(150,treeHeight)}
//	else {
//		var root= this.getRoot();
//		var twidth = 0;
//		var aaa="root";
//		for(var i=0;i<depth;i++){
//			aaa+=".getChildren()[0]";
//		}		
//		if (eval(aaa)){
//			twidth = eval(aaa+".getSize().width");
//			;
//		}
//		else {twidth=150;}
//		node.setSize(twidth/*maxWidth[depth]*/,treeHeight);}
//	
	////////////////
	var md = this.maxDepth(this.getRoot());
	//this.makeNode(this.getRoot(),md);
	////////////////
}

jTableLayout.prototype.calcTreeHeight = function(/*jNode*/ parent, /*array*/ children) {
	// (children의 width + hgap) + this.HGAP * (children.length - 1) 와 parent.width 비교해서 큰 값

	var parentHeight = parent.getSize().height;
	if(children == null || children.length == 0) {
		return parentHeight;
	}

	var child = null;
	var treeHeight = 0;
	for(var i = 0; i < children.length; i++) {
		child = children[i];
		treeHeight += parseInt(child.getTreeHeight());
	}
	treeHeight -= parseInt(children.length -1)*0.2;

	return Math.max(parentHeight, treeHeight);
}

jTableLayout.prototype.calcTreeWidth = function(/*jNode*/ parent, /*array*/ children) {
	// leaf 노드까지 높이를 계산한다.


	if(children == null || children.length == 0) {
		return parent.getSize().width;
	}

	var treeWidth = 0;
	for(var i = 0; i < children.length; i++) {
		treeWidth = Math.max(treeWidth,
						this.calcTreeWidth(children[i], children[i].getUnChildren())
			);
	}

	return treeWidth;
}

jTableLayout.prototype.calcTreeWidth1 = function(/*jNode*/ node) {
	// 노드 높이
	if (node.isRootNode()) {
		return 0;
	}
	else{
		var children=node.getParent().getChildren();
		if(children.length == 1) {
			return node.getSize().width;
		}

		var treeWidth = 0;
		for(var i = 0; i < children.length; i++) {
			treeWidth = Math.max(treeWidth, children[i].getSize().width);
		}
		return treeWidth;
	}
}

jTableLayout.prototype.placeNode = function(/*jNode*/ node, /*int*/relativeX, /*int*/relativeY) {
	
	if (node.isRootNode()) {
		node.setLocation(this.getRootX(), this.getRootY());
	} else {

		var x = 0;
		var y = 0;

		var prevNode = this.getPrevSibling(node);
		if(prevNode == null) {
			var parent = node.getParent();
			y = parseInt(parent.getLocation().y)/* - parseInt( parent.getTreeHeight()/2 ) + parseInt( parent.getSize().height /2 )
				+ parseInt(node.getTreeHeight()/2) - parseInt(node.getSize().height/2)
				+ parseInt(relativeY)*/;
		} else {
			y = parseInt(prevNode.getLocation().y) + parseInt(prevNode.getSize().height)/* + parseInt(prevNode.getTreeHeight() / 2)  + prevNode.getSize().height/2
				+ node.getTreeHeight()/2 - node.getSize().height/2
				+ parseInt(relativeY) */;
		}
		
		x = parseFloat(node.parent.getLocation().x)+parseFloat(node.parent.getSize().width)/* + parseFloat(relativeX)*/ ;

		node.setLocation(x, y);
	}
}

jTableLayout.prototype.resizeMap = function(/*int*/width, /*int*/height){
	var bResized = false;
	
	var oldXSize = RAPHAEL.getSize().width;
	var oldYSize = RAPHAEL.getSize().height;
	
	var newXSize = 0;
	var newYSize = 0;
	
	var locRoot = this.getRoot().getLocation();
	
	if(oldXSize < width * 2) {
		newXSize = width * 2;
		newYSize = oldYSize;
		bResized = true;
	}
	
	if(oldYSize < height * 2) {
		newXSize = oldXSize;
		newYSize = height * 2;
		bResized = true;
		
		this.placeNode(this.getRoot());
	}

	//보이는 위치를 바꿔준다.
	if(bResized) {
		RAPHAEL.setSize(newXSize, newYSize);
		this.placeNode(this.getRoot(), this.getRootX(), this.getRootY());
		
		this.map.work.scrollLeft += (newXSize - oldXSize)/2;
		this.map.work.scrollTop += (newYSize - oldYSize)/2;
	}
}

jTableLayout.prototype.getRootY = function() {
	var canvasSize = RAPHAEL.getSize();
	
	return Math.round( parseInt(canvasSize.height)*0.5) - parseInt(this.getRoot().body.getBBox().height)/2;
}

jTableLayout.prototype.getRootX = function() {
	var canvasSize = RAPHAEL.getSize();
	
	return Math.round( parseInt(canvasSize.width)*0.5) - parseInt(this.getRoot().body.getBBox().width)/2;
}

jTableLayout.prototype.getRoot = function() {
	return this.map.rootNode;
}


jTableLayout.prototype.getPrevSibling = function(node) {
	if(node.isRootNode()) {
		return null;
	}

	var index = node.parent.children.indexOf(node);

	if(index < 1) return null;

	return node.parent.children[index - 1];
}
