// Node object
function Node(id, pid, name, url, title, target) {
	this.id = id;
	this.pid = pid
	this.name = name;
	this.url = url;
	this.title = title;
	this.target = target;
	this.status = 2;	// 1 = none, 2 = expanded, 3 = collapsed, 4 = selected
	this.hi = 0;			// horizontal indent
	this.rc = -1;			// id of right child
	this.lc = -1;			// id of left child
	this.rc_ai = -1;	// index of right child node in aNodes array
	this.lc_ai = -1;	// index of left child node in aNodes array
	this.is_rc = false;
	this.is_lc = false;
	this.none_div_id;
	this.expanded_div_id; 
	this.collapsed_div_id;
	this.selected_div_id;
	this.leaf_div_id;
};

// Tree object
function dTree(objName) { 
	this.config = {
		target					: null,
		debugMode				:	false
	}
	this.icon = {
		node				: '/files/ntree3/img/node.gif',
		empty				: '/files/ntree3/img/empty.gif',
		vertical		: '/files/ntree3/img/line.gif',
		horizontal	: '/files/ntree3/img/vline.gif',
		cnx					: '/files/ntree3/img/X.gif',
		cn0					: '/files/ntree3/img/0.gif',
		cn1					: '/files/ntree3/img/1.gif',
		cnn					: '/files/ntree3/img/N.gif',
		joinLeft		: '/files/ntree3/img/joinleft.gif',
		joinRight		:	'/files/ntree3/img/joinright.gif',
		selected		: '/files/ntree3/img/selected.gif',
		notselected	:	'/files/ntree3/img/notselected.gif',
		plus				: '/files/ntree3/img/plus.gif',
		minus				: '/files/ntree3/img/minus.gif'
	}
	this.obj = objName;
	this.aNodes = [];		// stores nodes
	this.aiNodes = [];	// in order array of nodes
	this.aChildren = [];// list of child nodes of a node
	this.ta;						// matrix
	this.ta_rows = 0;		// matrix rows
	this.ta_cols = 0;		// matrix cols
	this.levels = 1;
	this.ind = 0;
	this.rootid = -1;
	this.aNames = [];
	this.aParamNames = [];
	this.aParamValues = [];
	this.aNodeIds= document.myform.level.value.split("_");
	if (document.myform.userprofile) {
		this.showCopies = true;
	} else {
		this.showCopies = false;
	}

};

// Adds a new node to the node array
dTree.prototype.add = function(id, pid, name, url, title, target) { 
	this.aNodes[this.aNodes.length] = new Node(id, pid, name, url, title, target);
};

// assign right and left children
dTree.prototype.rightorleft = function() {
	for (var i = 0; i < this.aNodes.length; i++) {
		for (var j = 1; j < this.aNodes.length; j++) {
			// if one node is parent node of another
			if(this.aNodes[j].pid == this.aNodes[i].id) {
				// if a right node is not filled, assign child to it else to the left node
				if(this.aNodes[i].rc == -1){
					// Debug: alert('rc' + ':' + this.aNodes[i].id + ':' + this.aNodes[j].id);
					this.aNodes[i].rc = this.aNodes[j].id;
					this.aNodes[i].rc_ai = j;
					this.aNodes[j].is_rc = true;
					//this.aNodes[i]._hc = true;
				} else {
					// Debug: alert('lc' + ':' + this.aNodes[i].id + ':' + this.aNodes[j].id);
					this.aNodes[i].lc = this.aNodes[j].id;
					this.aNodes[i].lc_ai = j;
					this.aNodes[j].is_lc = true;
				}
			}
		}
	}
}

// recurse inorder
dTree.prototype.inorder = function(index) {
	// get node corresponding to the node id
	var node = this.aNodes[index];

	// if there is a right child, increment indent, recurse
	if (node.rc_ai != -1) { this.ind++; this.inorder(node.rc_ai); } 

	// store indentation level in the node
	node.hi = this.ind; 
 
	// compute max indentation levels
	this.levels = Math.max(this.levels,node.hi);

	// push this node to aiNodes array
	this.aiNodes.push(node);

	// if there is a right child, increment indent, recurse
	if (node.lc_ai != -1) { this.ind++; this.inorder(node.lc_ai); }
	this.ind--;
}

dTree.prototype.build = function() {
	str = '';

	// create an array, one row for each node, n+2 levels to accomodate for the root and node names
	this.ta_rows = this.aiNodes.length;
	this.ta_cols = this.levels + 2; 
	this.ta = this.treeArray(this.ta_rows,this.ta_cols);
	var h = 0; // horizontal index

	for (var i = 0; i < this.aiNodes.length; i++) {
		h = this.aiNodes[i].hi; 
		this.aiNodes[i].matrixIndex = i;

		// if root node
		if (h == 0) {
			this.ta[i][0] = 1; this.rootid = this.aiNodes[i].id; this.ta[i][this.ta_cols - 1] = 'root';

		} else {
			// pre: node is not a root node

			// if the node is a right child, add joinRight symbol
			if (this.aiNodes[i].is_rc) { this.ta[i][h-1] = 2; }

			// if node is a left child, add joinLeft symbol
			if (this.aiNodes[i].is_lc) { this.ta[i][h-1] = 3; }

			// if has child, hub, else leaf
			if(this.aiNodes[i].rc != -1) { this.ta[i][h] = 1; } else { this.ta[i][this.ta_cols-2] = 5; }
			
			// print node name
			this.ta[i][this.ta_cols - 1] = this.aiNodes[i].name; 
		}
	}

	this.fillvlines(this.ta_rows,this.ta_cols); 

	// transposed 2D loop to add spaces and vertical lines
	for (var j = 0; j < this.ta_cols; j++)
	{
		var line_flag = false;
		for (var i = 0; i < this.ta_rows; i++)
		{
			if (line_flag == false && this.ta[i][j] == 2) { line_flag = true; }
			if (line_flag == true)
			{
				if (this.ta[i][j] == 3) { line_flag = false; } else if (this.ta[i][j] == 0) { this.ta[i][j] = 4; }
			}
		}
	}
}

// fill vertical line
dTree.prototype.fillvlines = function (r,c) { 
	var vline_flag = false;
	for (var i = 0; i < r; i++)
	{
		vline_flag = false;
		for (var j = 0; j < c; j++)
		{
			if (this.ta[i][j] == 2 || this.ta[i][j] == 3) {	vline_flag = true; }
			if (vline_flag == true)	{	
				if (this.ta[i][j] == 0)	{	this.ta[i][j] = 6; } 
				if (this.ta[i][j] == 1) { j = c; }
			}
		}
	}
}

// change between fungi, arthropoda, verterbrates trees
dTree.prototype.changetree = function(nid) { 
	var fungi = document.getElementById('Fung').style; 
	var arthropoda = document.getElementById('Arth').style; 
	var vertebrata = document.getElementById('Vert').style;
	fungi.display = 'none'; arthropoda.display = 'none'; vertebrata.display = 'none'; 
	var active = document.getElementById(nid).style;
	active.display='block';
	document.myform.tree.value=nid;
	if (nid == 'Fung') {
		document.myform.level.value='ASH_ASPC_ASPFC_ASPFU_ASPN_ASPO_ASPT_BO_CANA_CAND_CANG_CHA_CO_CR_DEB_EN_KL_LO_MA_NEO_NEU_PE_PHA_PICG_PICS_SCH_SCL_US_VA_YA_YEAS7_YEAST';
		this.aNodeIds= document.myform.level.value.split("_");
		this.getProfile();
		document.myform.submit();
	} else if (nid == 'Arth') {
		document.myform.level.value='Aa_Ag_Am_Ap_Bm_Cq_Da_De_Dg_Dme_Dmo_Dpe_Dps_Dpu_Dse_Dsi_Dv_Dw_Dy_Is_Nv_Ph_Tc';
		this.aNodeIds= document.myform.level.value.split("_");
		this.getProfile();
		document.myform.submit();
	} else if (nid == 'Vert') {
		document.myform.level.value='Ac_Bt_Cf_Ch_Cp_Dn_Do_Dr_Ec_Ee_Et_Fc_Ga_Gg_Hs_La_Md_Me_Ml_Mmul_Mmur_Mmus_Oa_Oc_Og_Ol_Op_Pc_Pv_Rn_Sa_St_Tb_Tg_Tn_Tr_Ts_Tt_Vp_Xt';
		this.aNodeIds= document.myform.level.value.split("_");
		this.getProfile();
		document.myform.submit();
  }
	document.getElementById(document.myform.level.value + '-plus').style.display = 'block';
	document.getElementById(document.myform.level.value + '-minus').style.display = 'none';
}

// print the tree
dTree.prototype.printTree = function() {
	var str = '';
	var nodeflag = false;
	var x = '<table border=1>';
	var str = '<table border=0><tr>'
		+ '<td align=right><div id="'+this.obj+'-cpn-header" style="display:none">'
		+	'<a onClick="' + this.obj + '.selectAllCPN(\'x\');"><img src="' + this.icon.cnx + '" /></a><img src="' + this.icon.empty + '" width=1>'
		+ '<a onClick="' + this.obj + '.selectAllCPN(\'0\');"><img src="' + this.icon.cn0 + '" /></a><img src="' + this.icon.empty + '" width=1>'
		+ '<a onClick="' + this.obj + '.selectAllCPN(\'1\');"><img src="' + this.icon.cn1 + '" /></a><img src="' + this.icon.empty + '" width=1>'
		+ '<a onClick="' + this.obj + '.selectAllCPN(\'n\');"><img src="' + this.icon.cnn + '" /></a>'
		+ '</div></td></tr><tr><td>';

	// for each node (row)
	for (var i = 0; i < this.ta_rows; i++)
	{
		// get node and nid
		var node = this.aiNodes[i];
		var nid = node.id;
		nodeflag = false;
		stack = ''; 
		x += '<tr>';

		// for every cell
		for (var j = 0; j < this.ta_cols - 1; j++)
		{
			this.aiNodes[i].none_div_id = nid + '-0';
			if (this.ta[i][j] == 0) { stack += '<img src="' + this.icon.empty + '" />'; }
			if (this.ta[i][j] == 6) { stack += '<img src="' + this.icon.horizontal + '" />'; } // horizontal line
			if (this.ta[i][j] == 2) { stack += '<img src="' + this.icon.joinRight + '" />'; } // r
			if (this.ta[i][j] == 3) { stack += '<img src="' + this.icon.joinLeft + '" />'; }  // L
			// if leaf node, just print it
			if (this.ta[i][j] == 5) {	// leaf 
				str += '<span class="dTreeNode" id="' + nid + '-leaf" style="display:block">' + stack +'<img src="' + this.icon.node + '" />';

			  // if the leaf node is a title e.g. fungi, vertebrate, insect, make it clickable
				if(node.title) { 
					str += '<img src="/files/ntree3/img/' + nid + '.png" onclick="' + this.obj + '.changetree(\'' + nid + '\');"/>';
				} else {
					str += '<img src="/files/ntree3/img/' + nid + '.png" />';
				}
				str += '<img src="' + this.icon.empty + '" width=5>';

				// if not a root node, create clickable copy number icons
				if (nid != 'Vert' && nid != 'Arth' && nid != 'Fung') {
				  str += '<img style="display:none; cursor:pointer" id="u-x-' + nid  + '" src="' + this.icon.notselected + '"  onClick="'+this.obj+'.checkIt(\'' + nid + '\',\'x\')">'
				        +'<img style="display:none; cursor:pointer" id="s-x-' + nid  + '" src="' + this.icon.selected + '"     >'
				        +'<img style="display:none; cursor:pointer" id="u-0-' + nid  + '" src="' + this.icon.notselected + '"  onClick="'+this.obj+'.checkIt(\'' + nid + '\',\'0\')">'
				        +'<img style="display:none; cursor:pointer" id="s-0-' + nid  + '" src="' + this.icon.selected + '"     >'
				        +'<img style="display:none; cursor:pointer" id="u-1-' + nid  + '" src="' + this.icon.notselected + '"  onClick="'+this.obj+'.checkIt(\'' + nid + '\',\'1\')">'
				        +'<img style="display:none; cursor:pointer" id="s-1-' + nid  + '" src="' + this.icon.selected + '"     >'
				        +'<img style="display:none; cursor:pointer" id="u-n-' + nid  + '" src="' + this.icon.notselected + '"  onClick="'+this.obj+'.checkIt(\'' + nid + '\',\'n\')">'
				        +'<img style="display:none; cursor:pointer" id="s-n-' + nid  + '" src="' + this.icon.selected + '"     >';
				}
				str += '</span>';

				this.aiNodes[i].leaf_div_id = nid + '-leaf';
				this.aNames.push(nid);
			} 
			if (this.ta[i][j] == 4) { stack += '<img src="' + this.icon.vertical + '" />'; }  // vertical line
			if (this.ta[i][j] == 1) { 

			if (!node.title) {
				str += '<span class="dtree" id="' + nid + '-plus" style="display:none">' + stack + '<a href="#" onclick="' + this.obj + '.oc(\'' + nid + '\');">' 
						 + '<img src="' + this.icon.plus + '" /></a></span>';
				str += '<span class="dtree" id="' + nid + '-minus" style="display:block">' + stack + '<a href="#" onclick="' + this.obj + '.oc(\'' + nid + '\');">' 
						+ '<img src="' + this.icon.minus + '" /></a></span>';
			} else {
				str += '<span class="dtree" id="' + nid + '-plus" style="display:none">' + stack + '<img src="' + this.icon.plus + '" /></span>';
				str += '<span class="dtree" id="' + nid + '-minus" style="display:block">' + stack + '<img src="' + this.icon.minus + '" /></span>';
			}
			this.aiNodes[i].collapsed_div_id = nid + '-plus';
			this.aiNodes[i].expanded_div_id = nid + '-minus';
		}
		x += '<td>' + nid + '</td>';
	}
	x += '</tr>';
	str += '<span class="dtree" id="' + nid + '-0" style="display:none"></span>';
	}
	x += '</table>';
	str += '</td>';
	str += '</td></tr></table>';
	
	return str;
}

// print specie names
dTree.prototype.printNames = function() {
	var str = '';
	for (var i = 0; i < this.aNames.length - 2; i++)
	{
		var node = this.aiNodes[i];
		str += '<div id="' + node.id + '-name" style="display:block">' + node.name + '</div>';
	}
	return str;
}

// get Node
dTree.prototype.getNodeIndex = function(nid) { 
	for (var i = 0; i < this.aiNodes.length; i++) {
		if (this.aiNodes[i].id == nid) { return i;}
	}
}

// recurse postorder to get a list of children
dTree.prototype.getChildren = function(nid) {
	var nodeindex = this.getNodeIndex(nid);
	var node = this.aiNodes[nodeindex];
	if (node.rc != -1) { this.getChildren(node.rc); } 
	if (node.lc != -1) { this.getChildren(node.lc); }
	//Debug: alert(node.id);
	this.aChildren.push(node);
};

dTree.prototype.changeNodeStatus = function(nid,status) {
	var nodeindex = this.getNodeIndex(nid); 
	var node = this.aiNodes[nodeindex];

	if (status == 3) {
		// expand
		if (node.collapsed_div_id) { var dvp = document.getElementById(node.collapsed_div_id).style; dvp.display = 'none'; }
		if (node.expanded_div_id) { var dvm = document.getElementById(node.expanded_div_id).style; dvm.display = 'block'; }
		//if (node.leaf_div_id) { var dv = document.getElementById(node.leaf_div_id).style; dv.display = 'block'; }
		//var dc = document.getElementById(node.id + '-cn').style; dc.display = 'block';
		//var dv = document.getElementById(node.none_div_id).style;	dv.display = 'none';
	}
	if (status == 2) {
		// collapse
		if (node.collapsed_div_id) { var dvp = document.getElementById(node.collapsed_div_id).style; dvp.display = 'block'; }
		if (node.expanded_div_id) { var dvm = document.getElementById(node.expanded_div_id).style;	dvm.display = 'none'; }
		//if (node.leaf_div_id) { var dv = document.getElementById(node.leaf_div_id).style; dv.display = 'none'; }
		//var dc = document.getElementById(node.id + '-cn').style; dc.display = 'none';
		//var dv = document.getElementById(node.none_div_id).style;	dv.display = 'block';
	}
}

// collapse or expand
dTree.prototype.oc = function(nid) { 
	// 2 = expanded, 3 = collapsed

	var nodeindex = this.getNodeIndex(nid);
	var node = this.aiNodes[nodeindex]; 
	(node.status == 2 ? node.status = 3 : node.status = 2); 

	for (var i = 0; i < this.aiNodes.length; i++) {
		var nde = this.aiNodes[i];
		if (nde.collapsed_div_id) { var dvp = document.getElementById(nde.collapsed_div_id).style; dvp.display = 'none'; }
		if (nde.expanded_div_id) { var dvm = document.getElementById(nde.expanded_div_id).style;	dvm.display = 'block'; }
	}	

	if (node.collapsed_div_id) { var dvp = document.getElementById(node.collapsed_div_id).style; dvp.display = 'block'; }
	if (node.expanded_div_id) { var dvm = document.getElementById(node.expanded_div_id).style;	dvm.display = 'none'; }

	document.myform.level.value = nid;
	this.aNodeIds= document.myform.level.value.split("_");
	this.getProfile();
	document.myform.submit();
}

// called when Show/Hide copy-number selectors is clicked
dTree.prototype.showhideCPN = function() { 
	if(this.showCopies){
		this.showCopies = false;
		for (var i = 0; i < this.aNodeIds.length; i++) {
			document.getElementById('s-x-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('s-0-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('s-1-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('s-n-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-x-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-0-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-1-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-n-'+this.aNodeIds[i]).style.display = 'none';
		}
		document.myform.getbyprofile.style.display = 'none';
		document.getElementById(this.obj+'-cpn-header').style.display = 'none';
		document.myform.userprofile.value = 'NULL';
	}	else {
		this.showCopies = true;
		for (var i = 0; i < this.aNodeIds.length; i++) {
			document.getElementById('s-x-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('s-0-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('s-1-'+this.aNodeIds[i]).style.display = 'inline';
			document.getElementById('s-n-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-x-'+this.aNodeIds[i]).style.display = 'inline';
			document.getElementById('u-0-'+this.aNodeIds[i]).style.display = 'inline';
			document.getElementById('u-1-'+this.aNodeIds[i]).style.display = 'none';
			document.getElementById('u-n-'+this.aNodeIds[i]).style.display = 'inline';
		}
		document.myform.getbyprofile.style.display = 'inline';
		document.getElementById(this.obj+'-cpn-header').style.display = 'block';
	}
}

dTree.prototype.checkIt = function(nid,active) {
	var t = ['x','0','1','n'];
	for (var i = 0; i < t.length; i++) {
		document.getElementById('s-'+t[i]+'-'+nid).style.display = 'none';
		document.getElementById('u-'+t[i]+'-'+nid).style.display = 'inline';
	}
	document.getElementById('s-'+active+'-'+nid).style.display = 'inline';
	document.getElementById('u-'+active+'-'+nid).style.display = 'none';
}

dTree.prototype.getProfile = function() {
	var x='';
	for (var j = 0; j < this.aNodeIds.length; j++) {
		if (document.getElementById('s-0-'+this.aNodeIds[j]).style.display == 'inline') {
			if (x != '') {x += ','}
			x += this.aNodeIds[j]+'=0';	
		}
		if (document.getElementById('s-1-'+this.aNodeIds[j]).style.display == 'inline') {
			if (x != '') {x += ','}
			x += this.aNodeIds[j]+'=1';
    }
		if (document.getElementById('s-n-'+this.aNodeIds[j]).style.display == 'inline') {
			if (x != '') {x += ','}
			x += this.aNodeIds[j]+'>1';
		}
		if (document.getElementById('s-x-'+this.aNodeIds[j]).style.display == 'inline') {
			if (x != '') {x += ','}
			x += this.aNodeIds[j]+' like \'%\'';
		}
	}
	document.myform.userprofile.value = x;
}

// open/close all
dTree.prototype.all = function() {
	this.oc(this.rootid);
}

// tree array - 2D matrix
dTree.prototype.treeArray = function(rows,cols) {
	var i;var j;
	var a = new Array(rows);
	for (i=0; i < rows; i++){
		a[i] = new Array(cols);
    for (j=0; j < cols; j++){
			a[i][j] = 0;
		}
	}   
	return(a);		
}

// print matrix - for debugging
dTree.prototype.printMatrix = function() {
	var str = '<table>';
	for (var i = 0; i < this.ta_rows; i++) {
		str += '<tr>';
		for (var j = 0; j < this.ta_cols; j++) {
			str += '<td>' + this.ta[i][j] + '</td>';			
		}
		str += '</tr>';
	}
	str += '</table>';
	document.write(str);
}

// print all nodes - for debugging
dTree.prototype.printNodes = function() {
	var str = '<br>';
	for (var i = 0; i < this.aNodes.length; i++) {
		str += this.aNodes[i].id + ':';
	}
	document.write(str);
}

// print traversed nodes - for debugging
dTree.prototype.printTraversedNodes = function() {
	var str = '<br>';
	for (var i = 0; i < this.aiNodes.length; i++) {
		str += this.aiNodes[i].id + ':';
	}
	document.write(str);
}

// print div tags - for debugging
dTree.prototype.printDivs = function() {
	var str = '<br>';
	for (var i = 0; i < this.aiNodes.length; i++)
	{
		str += i + ':' + this.aiNodes[i].none_div_id + ':' + this.aiNodes[i].expanded_div_id + ':' 
			+ this.aiNodes[i].collapsed_div_id + ':' + this.aiNodes[i].selected_div_id + ':' + this.aiNodes[i].leaf_div_id + '<br>';
	}
	document.write(str);
}

// print children - for debugging
dTree.prototype.printChildren = function() {
	var str = '<br>';
	for (var i = 0; i < this.aChildren.length; i++)
	{
		str += i + ':' + this.aChildren[i].id + '^';
	}
	document.write(str);	
}

// select all visible for copy numbers
dTree.prototype.selectAllCPN = function(active) {
	for (var i = 0; i < this.aNodeIds.length; i++) {
		this.checkIt(this.aNodeIds[i],active);
	}
}

// Outputs the tree to the page
dTree.prototype.toString = function() { 
	var str = '<div class="dtree" >\n';
	// find out which nodes are right children and which are left children
	this.rightorleft();
	// inorder tree traversal
	this.inorder(0);
	// build tree which would be shown
	this.build();
	// show tree
	str += this.printTree();
	// copy-number selector button
	str += '<br><font color="#blue"><b><a href="#" onclick="' + this.obj + '.showhideCPN();">Show/Hide copy-number selectors</a></b></font>'; 
	str += '</div>';
	return str;
};

