var tree;
var rankings = ["root","kingdom","phylum","lsidClass","phylorder","inforder","family","genus","species"];
var phylaSpecRankings = ["ncbiDomain","ncbiClass","ncbiOrder","ncbiGenus", "species"];
var treePath;
function init(path) {
	dwr.util.useLoadingMessage();
	checkPublishStatus();
	createTree();
	treePath = path;
}

var nodeClickedCache = {};
var nodeExistsCache = {};
var phylanodeExistsCache = {};
var phylanodeClickedCache = {};
var moltargetCache = {};
//var nodeIdCache = {};

// general functions for all ontologies
function createTree() {
	$("toxintable").style.display = "none";
	var category = document.getElementById("browseby").value;
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	if (tree) {
		tree.reset();
		tree.clearState();
		clearTable();
	}
		tree = new DynamicTreeBuilder("tree", path);
		tree.clearState();
    	tree.enableSetActive = true;
    	tree.init();
		tree.textClickListener.add(function() { textClicked(); });
		tree.nodeClickListener.add(function() { nodeClicked(); });
	switch (category) {
    	case "family":
    		populateFamilies();
    		nodeClickedCache = {};
    		break;
    	case "spider":
    		//nodeIdCache = {};
    		nodeClickedCache = {};
			nodeExistsCache = {};
    		makeSpiderNodes("Arachnida", "lsidClass", publicStatus, publishedStatus);
    		break;
    	case "moltarget":
    		makeMoltargetNodes();
    		break;
    	case "ptrans":
    		makePtransNodes();
    		break;
    	case "targetphyla":
    		phylanodeClickedCache = {};
			phylanodeExistsCache = {};
			makePhyleticSpecificityNodes("", "ncbiDomain", publicStatus, publishedStatus);
    		break;    	
    }
}

function checkPublishStatus() {
	//set public, published info for Roles except GroupAdmin 
	if (r == 1 ) {
		selectListOption(document.getElementById("publicStatus"), pri);
		if (pub != "hide" && pub != "") {
			makePublishedSelectBox();
			selectListOption(document.getElementById("publishedStatus"), pub);
		} else if (pub == ""){
			makePublishedSelectBox();
		} else {
			makePublishedSelectBox();
			selectListOption(document.getElementById("publishedStatus"), "YES");
			document.getElementById("published").style.display="none";
		}
	} 
	//set public, published info for GroupAdmin 
	if (r == 2 ) {
		if (pri == "" && pub == "") {
			document.getElementById("published").style.display="none";
			selectListOption(document.getElementById("publicStatus"), pri);
			makeGroupAdminWidgets();
		} else {
			alert(2);
			selectListOption(document.getElementById("publicStatus"), pri);
			if (pub != "hide" && pub != "") {
				alert(3);
				makePublishedSelectBox();
				selectListOption(document.getElementById("publishedStatus"), pub);
			} else if (pub == ""){
				alert(4);
				makePublishedSelectBox();
			} else if (pub == "hide") {
				alert(5);
				makePublishedSelectBox();
				selectListOption(document.getElementById("publishedStatus"), "YES");
				document.getElementById("published").style.display="none";
			}
		}
	}	
}

function makeArachnoAdminWidgets() {
	var published = document.getElementById("publicStatus").value;
	if (published === "NoNo") {
		document.getElementById("published").style.display="none";
		addOption(document.getElementById("publishedStatus"), "hide", "");
		selectListOption(document.getElementById("publishedStatus"), "hide");		
	} else {
		makePublishedSelectBox();
	}
	createTree();
}


function makeGroupAdminWidgets() {
	var published = document.getElementById("publicStatus").value;
	if (published === "YesYes" || published == "") {
		document.getElementById("published").style.display="none";
    	addOption(document.getElementById("publishedStatus"), "hide", "");
    	selectListOption(document.getElementById("publishedStatus"), "hide");
	} else {
		makePublishedSelectBox();
	}
	createTree();
}

function makePublishedSelectBox() {
	dwr.util.removeAllOptions(document.getElementById("publishedStatus"));
	document.getElementById("published").style.display="";
	addOption(document.getElementById("publishedStatus"), "YESANDNO", "Any");
	addOption(document.getElementById("publishedStatus"), "YES", "Curated");
	addOption(document.getElementById("publishedStatus"), "NO", "Uncurated");	
}

function removeAllOptions(selectbox) {
	for (var i = selectbox.options.length-1; i >= 0; i--) {
		selectbox.remove(i);
	}
}

function selectListOption(list, selectedId) {
	if (selectedId != -1) { 		
		var options = list.options;
	 	for (var i = 0; i < options.length; i++) {
	 		if (options[i].value == selectedId) {
	 			options[i].selected = true;
	 			break;
	 		}
	 	}
	 }
}

function addOption(selectbox, value, text, group) {
	var optn = document.createElement("option");
	optn.text = text;
	optn.value = value;
	if (group != null) {
		optn.label = text;
		group.appendChild(optn);
	}
	else {
		selectbox.options.add(optn);
	}
}

function nodeClicked() {
	var category = document.getElementById("browseby").value;
	var node = tree.getActiveNode();
	var level = node.getLevel();
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	switch (category) {
		case "family":
			if (getNodeId(node.dbid) === null) {
				nodeClickedCache[node.dbid] = node.id;	
				getFamilies(node.id, node.dbid);
			}
    		break;
    	case "spider":	
    		if (getNodeId(node.dbid) === null) { 	
				nodeClickedCache[node.dbid] = node.id;
				
		    	// determine the rank:
		    	var rank = "";
		    	if (rankings[level] != "species") {
			    	makeSpiderNodes(node.dbid, rankings[node.getLevel() + 3], publicStatus, publishedStatus);
				}
			}
	   		break;
    	case "targetphyla":
    		if (getPhyleticNodeId(node.dbid) === null) { 	
				phylanodeClickedCache[node.dbid] = node.id;
		    	if (phylaSpecRankings[level-1] != "species") {
		    		makePhyleticSpecificityNodes(node.dbid, phylaSpecRankings[node.getLevel()], publicStatus, publishedStatus);
				}
			}
	   		break;
	   	//case "moltarget":
	   	//	if (moltargetCache[node.dbid] == null) {
	    //		makeMoltargetNodes(node.dbid);
	    //		moltargetCache[node.dbid] = node.dbid;
    	//	}
    	//	break;
	}
}


function textClicked() {

	var category = document.getElementById("browseby").value;
	var node = tree.getActiveNode();
	
	document.getElementById("fastaForm").style.display = "";
	
	switch (category) {
		case "family":
			//if (node.text != "Unspecified toxin superfamily") {
	    		showToxinsByFamily(node.dbid);
    		//}
    		break;
    	case "spider":
    	
    		showToxinsByTaxonomy(node.dbid);
	   		break;
	   	case "ptrans":
	   		showToxinsByPtrans(node.dbid);
	   		break;
	   	case "moltarget":
	   		if (node.text != "root") {
		   		showToxinsByMoltarget(node.dbid);
			}
	   		break;
	   	case "targetphyla":	
	   		showPhyleticSpecificityNodes(node.dbid);
	   		break;
	}
}


function makeToxinTable(toxins) {
	UserManager.getCurrentUserAndRole(function (objects) {

		var user = objects[0];
		var role = objects[1];
		
		if (user != null) {
		var userGroup = user.userGroup.id;
		}
	dwr.util.removeAllRows("toxintablebody", { filter:function(tr) {
      	return (tr.id != "patterntt");
    }});
    	
    if (toxins.length > 0) {
		$("toxintable").style.display = "";
	}

	
	var toxinFuncs = [
		//function(toxin) { return toxin.id; },
		function(toxin) { return "<a href=\"toxincard.html?id="+toxin.id+"\" target=\"_blank\">"+toxin.name+"</a>"; },
		//function(toxin) { return toxin.toxinGroup.name; },
		function(toxin) { return toxin.displaySynonym; },
		function(toxin) { return toxin.lsidSpider.lsidCurrent.genus; },
		function(toxin) { return toxin.lsidSpider.lsidCurrent.species; }
	];
	if (m) {
		toxinFuncs.unshift( 
			function(toxin) {
				if (toxin.toxinOwner.id == userGroup) {
					if  (toxin.isShared && role == 'ROLE_ADMIN' || role == 'ROLE_ARACHNO_ADMIN') {
					return "<a href=\"usergroup/toxin.html?id="+toxin.id+"\" target=\"_blank\">modify</a>";
					} else if (!toxin.isShared && role == 'ROLE_GROUP_ADMIN') {
						return "<a href=\"usergroup/toxin.html?id="+toxin.id+"\" target=\"_blank\">modify</a>";
					}
				} else if (toxin.toxinOwner.id != userGroup) {
					if  (toxin.isShared && role == 'ROLE_ADMIN' || role == 'ROLE_ARACHNO_ADMIN') {
						return "<a href=\"usergroup/toxin.html?id="+toxin.id+"\" target=\"_blank\">modify</a>";
					}
				}
			}
		);
	}
	

	dwr.util.addRows("toxintablebody", toxins, toxinFuncs, {
		rowCreator:function(options) {
    		var row = document.createElement("tr");
    		if (options.rowIndex % 2 == 0) {
    	  		row.style.backgroundColor = "#FFFFFF";
	    	}
	    	else {
	    		row.style.backgroundColor = "#F3EFE6";
	    	}
    		return row;
  		},
  		cellCreator:function(options) {
    		var td = document.createElement("td");
    		td.className = "carddata";
    		return td;
  		},
  		escapeHtml:false
	});		

	var idList = "";
	for (var i = 0; i < toxins.length; i++) {	
		idList += toxins[i].id
		if (i < toxins.length - 1) {
			idList += ",";
		}
	}
	
	document.getElementById("toxinIdListStr").value = idList;
	});
}


function clearTable() {
	dwr.util.removeAllRows("toxintablebody", { filter:function(tr) {
      	return (tr.id != "patterntt");
    }});
   // $("toxintable").style.display = "display:none;";
}
	

function getNodeId(dbid) {
	for (var key in nodeClickedCache) {
		if (key == dbid) { return nodeClickedCache[key]; }
	}
	return null;
}


function getNodeIdByName(name) {
	for (var key in nodeExistsCache) {
		if (key == name) { return nodeExistsCache[key]; }
	}
	return null;
}


// moltarget section:
function makeMoltargetNodes() {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}

	//if (moltargetCache.length = 0) {
		
		ToxinManager.getMoltargetsWithToxinsByConditions(publicStatus, publishedStatus, 
			function(objects) {
				// sort the object by id:
			    if (objects.length > 0) {
				objects.sort(function(a,b) { return a[0] - b[0]; }); 
				//addMoltargetNode(objects[0],'folder',1);
				tree.active = moltargetCache[objects[0][0]];
				addMoltargetChildren(objects[0][0], objects);
			    }
			}
		);
	//}
}

function addMoltargetChildren(parentId, moltargets) {

	tree.active = moltargetCache[parentId];
	
	var children = new Array();
	for (var i = 0; i < moltargets.length; i++) {
		if (parentId == moltargets[i][2]) {
			addMoltargetNode(moltargets[i],'folder',1);
			children.push(moltargets[i]);
			//moltargets.splice(i, 1);
		}
	}
	
	for (var i = 0; i < children.length; i++) {
		addMoltargetChildren(children[i][0], moltargets);
	}
}



function addMoltargetNode(moltarget, type, makeExpandable) {
	var node = {"href":"", "title":"", "target":""};
	var displayName = moltarget[1];// + "(" + moltarget[3] + ")";
	//alert("adding "+displayName);
	if (tree.active) {
   		tree.insertInsideAtEnd("tree-"+moltarget[0], moltarget[0], displayName, type, node, makeExpandable);
  	}
	else {
	  	tree.insert("tree-"+moltarget[0], moltarget[0], displayName, type, node, makeExpandable);
	}   	
	moltargetCache[moltarget[0]] = "tree-"+moltarget[0];
}



// spider section
function makeSpiderNodes(parent, parentRank, publicStatus, publishedStatus) {
	ToxinManager.getToxinCountAndTaxaByParentTaxonByConditions(parent, parentRank, publicStatus, publishedStatus,
		function(taxa) {
			for (var j = 0; j < taxa.length; j++) {	
				if (parentRank == "genus") { addNode(taxa[j], 'folder', 0); }
				else { addNode(taxa[j], 'folder', 1); }
			}
		}
	);
}


function addNode(taxon, type, makeExpandable) {
	if (getNodeIdByName(taxon[1]) === null) {
		var node = {"href":"", "title":"", "target":""};
		var displayName = taxon[1] + " ("+ taxon[0]+ ")";
		if (tree.active) {
   			tree.insertInsideAtEnd("tree-"+(++tree.count), taxon[1], displayName, type, node, makeExpandable);
  		}
		else {
	   		tree.insert("tree-"+(++tree.count), taxon[1], displayName, type, node, makeExpandable);
	   	}
	   	nodeExistsCache[taxon[1]] = "tree-"+(tree.count);
	}
}

function showToxinsByTaxonomy(dbid) {
	var node = tree.getActiveNode();
	var level = node.getLevel();
	var taxon = rankings[level+3];
	
	// we should also get the parent of this taxon so that sp. species are unambiguous
	var parentTaxon = rankings[level+2];
	var parentDbId = node.parentNode.dbid

	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}


	
	ToxinManager.getToxinsByTaxonByConditions(dbid, taxon, parentDbId, parentTaxon, publicStatus, publishedStatus,
		function(toxins) {
			makeToxinTable(toxins);
		}
	);
}


// ptrans section
function makePtransNodes() {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	ToxinManager.getToxinCountAndPtransByConditions(publicStatus, publishedStatus,
		function(ptrans) {
			var node = {"href":"", "title":"", "target":""};
			
			for (var i = 0; i < ptrans.length; i++) {
				var ptran = ptrans[i];
				var displayName = ptran[2] + " (" + ptran[0] + ")";
				tree.insert("tree-"+(++tree.count), ptran[1], displayName, 'folder', node, 0);
			}
		}
	);
}


function showToxinsByPtrans(dbid) {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	ToxinManager.getToxinsByPtranTypeIdByConditions(dbid, publicStatus, publishedStatus,
		function(toxins) {
			makeToxinTable(toxins);
		}
	);
}

function showToxinsByMoltarget(dbid) {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	ToxinManager.getToxinsByMolTargetIdByConditions(dbid, publicStatus, publishedStatus,
		function(toxins) {
			makeToxinTable(toxins);
		}
	);
}



function showToxinsByFamily(dbid) {

	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}

	ToxinManager.getToxinsByFamilyIdByConditions(dbid, publicStatus, publishedStatus,
		function(toxins) {
			makeToxinTable(toxins);
   	 	}
   	);
}

// toxin families section
function populateFamilies() {

  ToxinSuperFamilyManager.getAllToxinSuperFamilies(function(toxinSuperFamilies) {
  		
  
  	// for superfamilies, these will be:
  	var where = 'after';
  	var type = 'folder';
  	var name;
  	var href = "";
  	var title = "";
  	var target = "";
  	
  	
    for (var i = 0; i < toxinSuperFamilies.length; i++) {
      toxinSuperFamily = toxinSuperFamilies[i];
      name = toxinSuperFamily.name;
      dbid = toxinSuperFamily.id;
      
        var node = {"href":href, "title":title, "target":target};  
     	tree.insert("tree-"+(++tree.count), dbid, name, type, node, 1);
    }
  });
}

function getFamilies(node_id, sf_id) {
	//tree.textClick(node_id);
	ToxinFamilyManager.getToxinFamiliesAndToxinCountsByToxinSuperFamilyId(sf_id, function(toxinFamilies) {
		
  		var where = 'after';
  		var type = 'folder';
  		var name;
  		var href = "";
  		var title = "";
  		var target = "";
  	
   		for (var i = 0; i < toxinFamilies.length; i++) {
   			
   		   	toxinFamily = toxinFamilies[i];
   		   	dbid = toxinFamily[0];
   	   		name = toxinFamily[1] + " ("+toxinFamily[2]+")";
      		var node = {"href":href, "title":title, "target":target};
      		if (tree.active) {
      	 		tree.insertInsideAtEnd("tree-"+(++tree.count), dbid, name, type, node, 0);
      		}
      		else {
      	 		tree.insert("tree-"+(++tree.count), dbid, name, type, node, 0);
      		}
      	}
  });
}


String.prototype.localeCompare = function (sOther) {
    if (this < sOther) return -1;
    else if (this > sOther) return 1;
    else return 0;
}

//Phyletic Specificity Section
function makePhyleticSpecificityNodes(rank, queryRank, publicStatus, publishedStatus) {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	ToxinManager.getPhyleticSpecificityWithToxinsByConditions(rank, queryRank, publicStatus, publishedStatus, function(objects) {		
					for (var j = 0; j < objects.length; j++) {
						if (queryRank == "species") { addPhyleticSpecificityNode(queryRank, objects[j], 'folder', 0); }
						else { addPhyleticSpecificityNode(queryRank, objects[j], 'folder', 1); }
					}
				}
			);
}

function addPhyleticSpecificityNode(queryRank, phyla, type, makeExpandable) {
	if (queryRank != "species") {
		var displayRank = queryRank.substring(4, queryRank.length);
	} else {
		var displayRank = queryRank;
	}
	if (getPhyleticNodeIdByName(phyla[0]) === null) {
		if (phyla[0] == "") {
			var displayName = displayRank + ": None  ("+ phyla[1]+ ")";;
		} else {
			if (queryRank == "species") {
				var fullname = phyla[0];
				var index = fullname.indexOf(" ");
				var name = fullname.substring(index, fullname.length);
				var displayName = "Species: " + name + " ("+ phyla[1]+ ")";	
			} else {
				var displayName = displayRank + ": " + phyla[0] + " ("+ phyla[1]+ ")";	
			}
		}
		var node = {"href":"", "title":"", "target":""};
		if (tree.active) {
   			tree.insertInsideAtEnd("tree-"+(++tree.count), phyla[0], displayName, type, node, makeExpandable);
  		}
		else {
	   		tree.insert("tree-"+(++tree.count), phyla[0], displayName, type, node, makeExpandable);
	   	}
	   	phylanodeExistsCache[phyla[0]] = "tree-"+(tree.count);
	}
}


function getPhyleticNodeIdByName(name) {
	for (var key in phylanodeExistsCache) {
		if (key == name) { return phylanodeExistsCache[key]; }
	}
	return null;
}

function getPhyleticNodeId(dbid) {
	for (var key in phylanodeClickedCache) {
		if (key == dbid) { return phylanodeClickedCache[key]; }
	}
	return null;
}

function showPhyleticSpecificityNodes(dbid) {
	var publicStatus = "public";
	var publishedStatus = "published";
	if (document.getElementById("publicStatus") != null) {
		publicStatus = document.getElementById("publicStatus").value;
	}
	if (document.getElementById("publishedStatus") != null) {
		publishedStatus = document.getElementById("publishedStatus").value;
	}
	var node = tree.getActiveNode();
	var level = node.getLevel();
	var rank = phylaSpecRankings[level-1];
	var parentRank = phylaSpecRankings[level];

	ToxinManager.getToxinsByPhyleticSpecificityRankByConditions(dbid, rank, parentRank, publicStatus, publishedStatus,
			function(toxins) {
				makeToxinTable(toxins);
	   	 	}
	   	);

}





