/**
 * Subject ontology related javascript module.  It has necessary function 
 * to build high interactive, scalable Tree Component in conjunction with Ajax 
 * and JSON.  It also support caching mechanism for persisting tree component's 
 * nodes.
 * 
 * @author Veeresh D.
 * @date March 2008
 */

var level = 0, i, str;
var nodeImg, nodeLink, nodeLevel;
var NodesChildren = new Array();
var Tree = new Array();
var treeImagesDir = "images/treeImages/";

var treeSub =
{
    /**
    Adds a node into the tree data structure.  After adding nodes, actual rendering or
    graphical preperation of tree in the browser will be done along with necessary 
    events over every nodes

    @param nodeId Uniqud id the child node
    @param nodeParentId Parent id of the node. It is used as a query parameter to fetch its children nodes
    @param nodeValue Name of the node
    @param nodeLevel Level or depth of the child node from the root node of the tree
    @param nodeType Type of node, either parent or child
    @param nodeTocId TOC Id of the node in the database.  It is used as a query parameter to fetch its articles
    @param lastNode 
    */
    addNode: function(nodeId, nodeParentId, nodeValue, nodeLevel, nodeType, nodeTocId, lastNode)
    {
        treeSub.appendChildNode();
	    level++;

	    nodeImg = treeImagesDir + "folder.gif";
	    nodeLink = treeImagesDir + "plus.gif";

	    if (nodeId == null)						//Unique Node ID
		    nodeId = level;
	    if (nodeParentId == null)
		    nodeParentId = "0";					//Node's Parent ID
	    if (nodeValue == null)
		    nodeValue = "Node" + nodeId;			//Node name
	    if (nodeLevel == null)
		    nodeLevel = "0";					//Depth from parent
	    if (nodeType == null)
		    nodeType = "1";					//Type of node (1= Parent, 0= Child)

	    if(nodeParentId != "")
	    {
		    var divs = document.getElementById("div" + nodeParentId);
		    str = "<DIV id=div" + nodeId + " style=\"position: relative;\">";

		    if ( nodeLevel > 0 )
		    {
			    for (i = 0; i < nodeLevel-2; i++)
				    str += "<img src=" + treeImagesDir + "line.gif />";							
		    }
		    if (NodesChildren[nodeParentId] == null)
			    NodesChildren[nodeParentId] = "";
    		
		    NodesChildren[nodeParentId] += "" + nodeId + ",";	//To keep track all its children
    		
		    if (nodeType == 0)	
			    nodeImg = treeImagesDir + "page.gif";
		    if (lastNode == null)	
			    lastNode = 0;				//For button add
    		
		    nodeLink = treeSub.defineLinkType(nodeType, lastNode);
    		
		    if (nodeId==1)
		    {
			    nodeImg = treeImagesDir + "globe.gif";							//Root most element
			    nodeValue = "Ontology Forest";
			    nodeLink = treeImagesDir + "nolines_plus.gif";
		    }
    		
		    str += "<img class=clickPtr onclick=\"treeSub.checkNode(" + nodeId +")\" id=img" + nodeId;
		    str += " name=imgname" + nodeParentId +" src=\"" + nodeLink + "\"/>";
    		
		    var nodeToolTip = nodeValue;
		    nodeToolTip = nodeToolTip.replace("<font color=saxblue>","");
		    nodeToolTip = nodeToolTip.replace("</font>","");
    		
		    //str += "<a href=\"#\" onclick=\"treeSub.checkNode(" + nodeId + "),treeSub.getSubjectResults('" + nodeTocId + "','" + nodeToolTip + "')\" title='" + nodeToolTip +"'>";
		    str += "<A href=?subject=" + nodeTocId + "&term=" + escape(nodeToolTip) + " onclick=\"return treeSub.checkNode(" + nodeId + "),treeSub.getSubjectResults('" + nodeTocId + "','" + nodeToolTip + "')\" title='" + nodeToolTip +"'>";
            str += "<img src=\"" + nodeImg + "\" title='" + nodeToolTip +"'/>";	//Either Folder or Item icon
		    str += nodeValue;								                    //Node name/value
		    str += "</a></DIV>";

		    if ( getBrowserName() == "Safari" || getBrowserName() == "Mozilla" )
		        divs.innerHTML += str;
		    else
		        divs.insertAdjacentHTML("afterEnd", str);
		    //divs.innerHTML += str;
	    }
    },
    
    /**
    Get subject related articles

    @param subjectNodeName TOC id of the node to fetch all of its articles
    @param subjectNodeName Node name
    */
    getSubjectResults: function(subjectNodeID, subjectNodeName)
    {
	    treeSub.getNodeArticles(subjectNodeID, subjectNodeName);
	    latestSearchResultFunCall = "treeSub.getNodeArticles('" + subjectNodeID + "','" + subjectNodeName + "')";					
	    return false;
    },
    
    /**
    Defines the type of link associated with parent and its children node.
    Depends on the type of node, it generates a image just below its parent
    or children nodes( like Plus, Last plus, last node)

    @param nType Node type, 1 for parent and 0 for children/leaf node
    @param ln Binary state of last node.  0 for last node, and not 0 for not last node
    */
    defineLinkType: function(nType, ln)
    {
	    var ret;
	    switch(Number(nType))
	    {
		    case 0:
					    ret = (ln==0)? "joinbottom.gif" : "join.gif";
					    break;
		    case 1:
					    ret = (ln==0)? "plusbottom.gif" : "plus.gif";
					    break;				
	    }
	    return (treeImagesDir + ret);
    },
    
    /**
    It Checks the status of the node, based on it, it either opens or closes the
    parent node.  It may also need to manage security accesses and data caching 
    mechanism tasks

    @param j Identifier of the node
    */
    checkNode: function(j)
    {
        var nodeIname;
	    nodeIname = getURIFileName(document.getElementById("img" + j).src);
	    if ( isSameString(nodeIname, "nolines_plus.gif") || isSameString(nodeIname, "plus.gif") || isSameString(nodeIname,"plusbottom.gif"))
	    {
		    if ( NodesChildren[j]== null)
		    {
			    treeSub.getChildrenNodes(j);
			    //var img = document.getElementById("img" + j);
			    //img.src = (treeImagesDir + "minus.gif");
			    /* Following two lines of code is for showing '-' symbol to show the node opening after getting its children */
	            //var img = document.getElementById("img" + j);
		        //img.src = (treeImagesDir + "minus.gif");		
		    }
		    else
			    treeSub.openParent(j);	//If Node has already been loaded
	    }
	    else
		    treeSub.closeParent(j);
    },
    
    /**
    Expands or opens the parent node of the tree

    @param k Identifier of the parent node
    */
    openParent: function(k)
    {
        if( NodesChildren[k] != null)
	    {
		    var cnode;
		    
		    if ( document.getElementById("img" + k) )
    	        document.getElementById("img" + k).src = (treeImagesDir + "minus.gif");
	        
		    var childrenIds = new Array();
		    childrenIds = NodesChildren[k].split(",");

		    for(var i = 0; i < childrenIds.length-1; i++)
		    {
			    cnode = document.getElementById("div" + childrenIds[i]);
			    cnode.style.display = '';
			    treeSub.openParent(childrenIds[i]);
		    }
	    }
    },
    
    /**
    Closes the parent node of the tree

    @param l Identifier of the parent node
    */
    closeParent: function(l)
    {	
	    if (NodesChildren[l] != null)
	    {
		    var cnode;
		    var img = document.getElementById("img" + l);
		    img.src = treeImagesDir + "plus.gif";

		    var childrenIds = new Array();
		    childrenIds = NodesChildren[l].split(",");

		    for (var i = 0; i < childrenIds.length - 1; i++)
		    {
			    cnode = document.getElementById("div" + childrenIds[i]);
			    cnode.style.display = "none";
			    treeSub.closeParent(childrenIds[i]);
		    }
	    }
    },
    
    /**
    Get the children nodes from the server dynamically

    @param rid Parent id of the node
    */
    getChildrenNodes: function(rid)
    {
        var ajaxRequest = zXmlHttp.createRequest();	
	    showNotification('subTreeNote', 'Loading...', 0);
        ajaxRequest.onreadystatechange = function()
	    {
	        if(ajaxRequest.readyState == 4)
		    {
		        if (ajaxRequest.status == 200)
			    {		
			        treeSub.renderJSONTreeArrays(ajaxRequest.responseText, rid);
			    }
			    else
			    {   
			        hideNotification('subTreeNote');
				    showFallBackNotification('leftPanelSubjectTreeBoxDiv',"Unable to get server response.", "treeSub.getSubTreeInitData()");
			        //alert("Unable to get subject trees' children nodes. Please try again!: \n\n" + ajaxRequest.responseText.substring(1,2000)); 
			    }		
		    }
	    }
	    ajaxRequest.open("GET", ROOT_DB_URL + "ontology.action?parentNodeId=" + rid + "&ontologyType=subjects" + ((loginStatus == false) ? "" : "&nullParam=" + new Date()), true);	//Struts class source
	    ajaxRequest.send(null);
    },

    /**
    Render/Retrive the children meta data of tree and adds/updates the tree component

    @param myJSONtext JSON data object containing children meta data of tree
    */
    renderJSONTreeArrays: function(myJSONtext, nodeNo)
    {
        var myObject = eval('(' + myJSONtext + ')');
	    var lnode = 0;
	    if ( myObject.ontologyNode.length > 0 && myObject.ontologyNode[0].statusMessage == "failure" )
	    {
	        hideNotification('subTreeNote');
	        //alert("Please login to access Subject Ontology tree");
	        showNotification('subTreeNote', '<img src=images/alertAttention.gif /> Please login to expand tree', 3);
	        return ;
	    }
	    else if ( myObject.ontologyNode.length == 0 )
	    {
	        hideNotification('subTreeNote');
		    showFallBackNotification('leftPanelSubjectTreeBoxDiv',"Unable to get server response.", "treeSub.getSubTreeInitData()");			        
		    return ;
	    }

	    if ( document.getElementById("img" + nodeNo) )
	        document.getElementById("img" + nodeNo).src = (treeImagesDir + "minus.gif");
		
	    if ( getBrowserName() == "Safari" || getBrowserName() == "Mozilla" )
	    {
	        for (var i = 0; i < myObject.ontologyNode.length; i++)
	        {
		        treeSub.addNode(myObject.ontologyNode[i].nodeId, myObject.ontologyNode[i].rootId, myObject.ontologyNode[i].name, Number(myObject.ontologyNode[i].displayLevel)-1, myObject.ontologyNode[i].type, myObject.ontologyNode[i].tocID, lnode);
		        lnode = 1;
	        }
	    }
	    else
	    {
	        for (var i = myObject.ontologyNode.length - 1; i >= 0; i--)
	        {
		        treeSub.addNode(myObject.ontologyNode[i].nodeId, myObject.ontologyNode[i].rootId, myObject.ontologyNode[i].name, Number(myObject.ontologyNode[i].displayLevel)-1, myObject.ontologyNode[i].type, myObject.ontologyNode[i].tocID, lnode);
		        lnode = 1;
	        }
	    }
	    hideNotification('subTreeNote');
    },
    
    /**
    Get the articles of a selected node of the tree component from the server

    @param nodeTOCId Identifier/TOC id of the tree node
    */
    getNodeArticles: function(nodeTOCId, nodeName)
    {
	    var ajaxRequest = zXmlHttp.createRequest();
    	showTopNotification();
    	
	    ajaxRequest.onreadystatechange = function()
	    {
		    if(ajaxRequest.readyState == 4)
		    {
			    if (ajaxRequest.status == 200)
			    {	
				    hideTopNotification();
				    global.variables.recentSearchType = "subjectOntologySearch";
				    global.setSaveSearchParams(nodeTOCId, "ontologySubject");
				    var flag = searchResults.renderJSONSearchResults(ajaxRequest.responseText, nodeName, 1);
				    if ( flag == false )
        		    {
        		        return false;   // Do nothing when no results
        		    }
				    if ( totalArticleResultsFound != 0 )
					    initResultPages(totalArticleResultsFound, 10, nodeTOCId, "ontology", nodeName);   //Pagination component initialization
    				
				    historyIsItResultDetails = 1;
	                parityHistory.setInHistory();
			    }
			    else
			    {
				    hideTopNotification();//hideNotification('subTreeNote');
				    alert("Unable to get search results articles for \"" + nodeName + "\". Please try again"); 
			    }
		    }
	    }
	    //alert("url=" + ROOT_DB_URL + "search.action?nodeID=" + nodeTOCId + "&nodeLabel=" + escape(nodeName) + "&ontologyType=subjects");	//Struts class source
	    //ajaxRequest.open("GET", ROOT_DB_URL + "search.action?nodeID=" + nodeTOCId + "&nodeLabel=" + escape(nodeName) + "&ontologyType=subjects" + ((loginStatus == false) ? "" : "&nullParam=" + new Date()), true);	//Struts class source
	    ajaxRequest.open("GET", ROOT_DB_URL + "search.action?nodeID=" + nodeTOCId + "&nodeLabel=" + escape(nodeName) + "&ontologyType=subjects&nullParam=" + new Date(), true);	//Struts class source
	    //ajaxRequest.open("GET", ROOT_DB_URL + "search.action?nodeID=mohan.10186&nodeLabel=" + escape(nodeName) + "&ontologyType=subjects" + ((loginStatus == false) ? "" : "&nullParam=" + new Date()), true);	//Struts class source
	    ajaxRequest.send(null);
    },
    
    getSubTreeInitData: function()
    {
        document.getElementById("leftPanelSubjectTreeBoxDiv").innerHTML = "<div id=\"div1\"></div><BR/>";
        
        NodesChildren.length = 0;
        
        treeSub.addNode(2, 1, 'Subjects', 1, 1, 'paruti.2000');
        treeSub.getChildrenNodes(2);
        if ( getBrowserName() == "Safari" || getBrowserName() == "Mozilla" )
	    {
	        if (document.getElementById("div2"))
	            document.getElementById("div2").innerHTML = "";	//To remote root note "Subjects"
	    }
	    else
	    {
	        if (document.getElementById("div2"))
	            document.getElementById("div2").style.display = "none";	//To remote root note "Subjects"    	
	    }
    },
    
    /**
    Create or Adds a new object prototype for appending child node mechanism.
    It will detects the internal object's method, based on status it creates
    this browser level function to add new children nodes to existing tree
    */
    appendChildNode: function()
    {
	    if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement)
	    {
		    HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
		    {
			    switch (where)
			    {
				    case 'beforeBegin':
					    this.parentNode.insertBefore(parsedNode,this)
					    break;
				    case 'afterBegin':
					    this.insertBefore(parsedNode,this.firstChild);
					    break;
				    case 'beforeEnd':
					    this.appendChild(parsedNode);
					    break;
				    case 'afterEnd':
					    if (this.nextSibling)
						    this.parentNode.insertBefore(parsedNode,this.nextSibling);
					    else
						    this.parentNode.appendChild(parsedNode);
					    break;
			    }
		    }
            
		    HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
		    {
			    var r = this.ownerDocument.createRange();
			    r.setStartBefore(this);
			    var parsedHTML = r.createContextualFragment(htmlStr);
			    this.insertAdjacentElement(where,parsedHTML)

		    }
		    
		    HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
		    {
			    var parsedText = document.createTextNode(txtStr)
			    this.insertAdjacentElement(where,parsedText)
		    }
	    }
    }
}

