// -------------------------------------------------------------------------
// Functions for selecting topics from a treeview. 
// -------------------------------------------------------------------------

var g_oTopicTreeDiv = null; // Reference to the div tag where the tree will be created
var g_SelectedTopicIndex = -1; // Index of the selected topics. Only used when static tree specified.
var g_arrTopicNames = new Array(); // Topic names used to build the tree. Ex. new Array("Windows", "Windows/Printers", "Office", "Office/Word");
var g_sTopicNameDelimiter = "/"; // The delimiter between levels of the node names
var g_sAllTopicsTitle = "All topics"; // Title used for the root node
var g_sRootTopic = ""; // The topic to be used as the root topic ex. Windows/Printers
var g_bTopicTreeCollapsible = true; // True if the treeview nodes should be collabsible
var g_nDefaultExpandLevel = 1; // How many levels that should be expanded from start. 0 = all levels
var g_oTopicTree = null; // Contains the tree using TopicNode objects
var g_nChildNodeIndent = 19; // Indent for child nodes
var g_nFirstLevelIndent = 4; // Indent for child nodes on first level
var g_sPreselectTopic = ""; // NJ 2008-04-10 use this parameter to pre-select a certain topic 
var g_arrRootTopics = new Array(); // Holds the root topics that should be viewed 
var g_arrTopicNameObjects = new Array(); // An array of topic name objects { displayName, topicName }

function makeTopicTree(oDiv, arrTopicNames, sAllTopicsTitle, nIndent, sRootTopic)
{
	// Fall back to root topic name
	if ((g_arrRootTopics.length == 0) && sRootTopic) {
		g_arrRootTopics[0] = sRootTopic;
	}
	// Set the root topic if needed
	if ((g_arrRootTopics.length > 0) && !sRootTopic) {
		//sRootTopic = g_arrRootTopics[0];
		sRootTopic = "";
	}
		
	if (g_bTopicTreeCollapsible)
		makeTopicTreeCollapsible(oDiv, arrTopicNames, sAllTopicsTitle, nIndent, sRootTopic);
	else
		makeTopicTreeStatic(oDiv, arrTopicNames, sAllTopicsTitle, nIndent, sRootTopic);
}

function makeTopicTreeCollapsible(oDiv, arrTopicNames, sAllTopicsTitle, nIndent, sRootTopic)
{
	arrTopicNames = fixTopicArray(arrTopicNames);
	//arrTopicNames = applyRootTopicToTopicArray(sRootTopic, arrTopicNames);
	g_arrTopicNameObjects =	applyRootTopicsToTopicArray(g_arrRootTopics, arrTopicNames);
	arrTopicNames = getDisplayNamesFromTopicNameObjects(g_arrTopicNameObjects);
		
	g_arrTopicNames = arrTopicNames;
	g_sAllTopicsTitle = sAllTopicsTitle;
	g_sRootTopic = sRootTopic;
	g_oTopicTree = createTopicTreeFromTopicNames(g_arrTopicNames);
	initTopicTreeState(g_oTopicTree);

	res = createTopicTreeHTML(g_oTopicTree);
	oDiv.innerHTML = res;
}

function makeTopicTreeStatic(oDiv, arrTopicNames, sAllTopicsTitle, nIndent, sRootTopic)
{
	arrTopicNames = fixTopicArray(arrTopicNames);
	arrTopicNames = applyRootTopicToTopicArray(sRootTopic, arrTopicNames);

	g_arrTopicNames = arrTopicNames;
	g_sAllTopicsTitle = sAllTopicsTitle;
	g_sRootTopic = sRootTopic;

	var res = '<table cellpadding=0 cellspacing=0>';
	
	// Add all topics (index -1)
	var sMenuItemStyle = (g_SelectedTopicIndex == - 1 ? "topicTreeMenuItemSelected" : "topicTreeMenuItem");
	var sMenuItemFolderStyle = (g_SelectedTopicIndex == - 1 ? "topicTreeFolderImageSelected" : "topicTreeFolderImage");
	res += 
		'<tr><table cellpadding=0 cellspacing=0><tr><td></td>' +
		'<td id="oTopicTreeMenuItemFolderImage0" class="' + sMenuItemFolderStyle + '" nowrap></td><td>' +
		'<table id="oTopicTreeMenuItem0" cellpadding=0 cellspacing=0 class="' + sMenuItemStyle + '" ' +
		'onmouseover="this.className=\'topicTreeMenuItemHover\'" ' +
		'onmouseout="this.className=\'' + sMenuItemStyle + '\'" ' +
		'onclick="selectTopicIndex(-1)" ' +
		'><tr><td nowrap title="' + sAllTopicsTitle + '">' + sAllTopicsTitle + '</td></tr></table>' +
		'</td></tr></table></tr>';
	
	for (var i = 0; i < arrTopicNames.length; i++) 
	{
		var sTopicName = arrTopicNames[i];
		var arrTopicNameParts = sTopicName.split(g_sTopicNameDelimiter);
		sMenuItemStyle = (i == g_SelectedTopicIndex ? "topicTreeMenuItemSelected" : "topicTreeMenuItem");
		sMenuItemFolderStyle = (i == g_SelectedTopicIndex ? "topicTreeFolderImageSelected" : "topicTreeFolderImage");
		
		var totalIndent = 0;
		for (var j = 0; j < arrTopicNameParts.length - 1; j++) 
			totalIndent += nIndent;
		totalIndent += nIndent; // Add one indent level so the topics is below All Topics
		
		var sMenuItem = 
			'<tr><table cellpadding=0 cellspacing=0><tr><td width="' + totalIndent + '" nowrap></td>';
		sMenuItem += 
			'<td id="oTopicTreeMenuItemFolderImage' + (i + 1) + '" class="' + sMenuItemFolderStyle + '" nowrap></td><td>';
		sMenuItem += 
				'<table id="oTopicTreeMenuItem' + (i + 1) + '" cellpadding=0 cellspacing=0 class="' + sMenuItemStyle + '" ' +
				'onmouseover="this.className=\'topicTreeMenuItemHover\'" ' +
				'onmouseout="this.className=\'' + sMenuItemStyle + '\'" ' +
				'onclick="selectTopicIndex(' + i + ')" ' +
				'><tr>';
		var sLastTopicPart = arrTopicNameParts[arrTopicNameParts.length - 1];
		sMenuItem += "<td nowrap title='" + sLastTopicPart + "'>" + sLastTopicPart + "</td>";
		sMenuItem += "</tr></table>";
		sMenuItem += '</td></tr></table></tr>';
		// Add the menu item
		res += sMenuItem;
	}
	res += "</table>";

	oDiv.innerHTML = res;
}

function getTopicIndex(sTopicPath)
{
	for (var i = 0; i < g_arrTopicNames.length; i++) 
	{
		if (sTopicPath == g_arrTopicNames[i]) 
			return i;
	}
	return -1;
}

function addToStringArray(str, arr, bIgnoreDuplicates)
{
	if (bIgnoreDuplicates) 
	{
		for (var i = 0; i < arr.length; i++) 
		{
			if (str == arr[i]) 
				return;
		}
	}
	arr[arr.length] = new String(str);
}

// Makes sure that the array contains topics on all levels

function fixTopicArray(arrTopicNames) 
{
	var arrTopicNamesFixed = new Array();
	for (var i = 0; i < arrTopicNames.length; i++) 
	{
		var sTopicName = arrTopicNames[i];
		var arrTopicNameParts = sTopicName.split(g_sTopicNameDelimiter);
		var sTopicPath = "";
		for (var j = 0; j < arrTopicNameParts.length; j++) 
		{
			sTopicPath += arrTopicNameParts[j];
			addToStringArray(sTopicPath, arrTopicNamesFixed, true); 
			sTopicPath += g_sTopicNameDelimiter;
		}
	}
	return arrTopicNamesFixed;
}

// Removes topics that are not below the root topic
function applyRootTopicToTopicArray(sRootTopic, arrTopicNames) {
	if (sRootTopic == "")
		return arrTopicNames;

	if ((sRootTopic != "") && (sRootTopic[sRootTopic.length] != '/')) 
		sRootTopic += "/";

	var sRootTopicNoCase = sRootTopic.toLowerCase();
	var arrTopicNamesFixed = new Array();
	for (var i = 0; i < arrTopicNames.length; i++) 
	{
		var sTopicName = arrTopicNames[i];
		var sTopicNameNoCase = sTopicName.toLowerCase();
		var pos = sTopicNameNoCase.indexOf(sRootTopicNoCase);
		if (pos == 0) {
			sTopicName = sTopicName.substring(sRootTopic.length);
			addToStringArray(sTopicName, arrTopicNamesFixed, true); 
		}
	}
	return arrTopicNamesFixed;
}

// Removes topics that are not below the root topics. Returns a new array containing 
// objects that holds the display name path (to make the tree of) and the actual topic name 
function applyRootTopicsToTopicArray(arrRootTopics, arrTopicNames) {

	// Make sure the root topics are not blank
	var arrRootTopicsFixed = new Array();
	for (var i = 0; i < arrRootTopics.length; i++) 
	{
		var sRootTopic = arrRootTopics[i];
		if (sRootTopic != "") {
			arrRootTopicsFixed[arrRootTopicsFixed.length] = sRootTopic;
		}
	}
	arrRootTopics = arrRootTopicsFixed;	
		
	var arrTopics = new Array();
	for (var i = 0; i < arrTopicNames.length; i++) 
	{
		var sTopicName = arrTopicNames[i];
		var sTopicNameLowerCase = sTopicName.toLowerCase();
		if (arrRootTopics.length > 0) {
			for (var j = 0; j < arrRootTopics.length; j++) 
			{
				var sRootTopic = arrRootTopics[j]; 
				var sRootTopicLowerCase = sRootTopic.toLowerCase();
				if (sTopicNameLowerCase == sRootTopicLowerCase) {
					if (arrRootTopics.length > 1) {
						// If we have more than one root topics - add the last part if the root topic to the list
						var arrTopicParts = sRootTopic.split("/");
						sDisplayName = arrTopicParts[arrTopicParts.length - 1];
						arrTopics[arrTopics.length] = new TopicNameObject(sDisplayName, sTopicName);
						continue;
					}
				}
								
				// Handle subtopics to root topic
				if ((sRootTopic != "") && (sRootTopic[sRootTopic.length] != '/')) 
					sRootTopic += "/";
				sRootTopicLowerCase = sRootTopic.toLowerCase();
				var pos = sTopicNameLowerCase.indexOf(sRootTopicLowerCase);
				if (pos == 0) {
					var sDisplayName = sTopicName.substring(sRootTopic.length);
					// If there are more than one root topic add the last part of the root 
					// topic name to the display name. Ex. if Windows and Office are root topics it will display like this:
					// All topics
					//   Windows
					//	 Office
					if (arrRootTopics.length > 1) {
						var arrTopicParts = sRootTopic.split("/");
						// Note: The last part is blank because we always add a slash at the end
						sDisplayName = arrTopicParts[arrTopicParts.length - 2] + "/" + sDisplayName;
					}
					if (sDisplayName != "") {
						arrTopics[arrTopics.length] = new TopicNameObject(sDisplayName, sTopicName);
					}
				}
			}
		} else {
			var sDisplayName = arrTopicNames[i];
			arrTopics[arrTopics.length] = new TopicNameObject(sDisplayName, sTopicName);
		}
	}
	return arrTopics;
}

function getDisplayNamesFromTopicNameObjects(arrTopicNameObjects) {
	var res = new Array();
	for (var i = 0; i < arrTopicNameObjects.length; i++) {
		res[res.length] = arrTopicNameObjects[i].displayName;	
	}
	return res;
}

function findTopicNameForDisplayName(sDisplayName) {
	for (var i = 0; i < g_arrTopicNameObjects.length; i++) {
		var t = g_arrTopicNameObjects[i];
		if (t.displayName == sDisplayName) {
			return t.topicName;
		}
	}
	return null;
}

function findChildTopicNode(parentNode, sTopicName) {
	for (var i = 0; i < parentNode.children.length; i++) {
		if (parentNode.children[i].topicName.toLowerCase() == sTopicName.toLowerCase())
			return parentNode.children[i];
	}
	return null;
}

function createChildTopicNode(parentNode, sTopicName, sTopicPath) {
	var topicNode = findChildTopicNode(parentNode, sTopicName);
	if (topicNode == null) {
		topicNode = new TopicNode(sTopicName, sTopicPath);
		topicNode.parent = parentNode;
		parentNode.children[parentNode.children.length] = topicNode;
	}
	return topicNode;
}

function createTopicNodeFromPath(rootNode, sTopicPath) {
	var arrTopicNameParts = sTopicPath.split(g_sTopicNameDelimiter);
	var currentParentNode = rootNode;
	var currentTopicPath = "";
	var currentTopicName = "";
	for (var i = 0; i < arrTopicNameParts.length; i++) {
		currentTopicName = arrTopicNameParts[i];
		currentTopicPath += (currentTopicPath != "" ? "/" : "") + currentTopicName;
		//currentParentNode = createChildTopicNode(currentParentNode, currentTopicName, currentTopicPath);
		var fullTopicPath = findTopicNameForDisplayName(currentTopicPath);
		//if (fullTopicPath == null) alert('not found for ' + currentTopicPath);
		currentParentNode = createChildTopicNode(currentParentNode, currentTopicName, fullTopicPath);
	}
}

function createTopicTreeFromTopicNames(arrTopicNames) {
	var rootNode = new TopicNode(g_sAllTopicsTitle, ""); // Root node (all topics)
	
	// Add all root topics as the root node
	rootNode.topicPaths = new Array();
	for (var i = 0; i < g_arrRootTopics.length; i++) { 
		rootNode.topicPaths[rootNode.topicPaths.length] = g_arrRootTopics[i];
	}
    rootNode.selected = true;

	for (var i = 0; i < arrTopicNames.length; i++) 
	{
		var sTopicName = arrTopicNames[i];
		createTopicNodeFromPath(rootNode, sTopicName);
	}
	return rootNode;
}

function initTopicTreeState(node) {
	var arrTopicNodes = getTopicNodeArray(node);
	for (var i = 0; i < arrTopicNodes.length; i++) {
		var node = arrTopicNodes[i];

        // NJ 2008-04-10 Changed so that a topic can be selected
        if (g_sPreselectTopic != "") {
            thisNodeFullName = node.topicName;
            if (!node.isRoot()) {
                parentNode = node.parent;
                while (!parentNode.isRoot()) {
                    thisNodeFullName = parentNode.topicName + '/' + thisNodeFullName;
                    parentNode = parentNode.parent;
                }
            }
            if (node.isRoot()) {
            	node.selected = false;
            }
            
            if (g_sRootTopic != '') {
                thisNodeFullName = g_sRootTopic + '/' + thisNodeFullName;
            }
            
            if ((g_sPreselectTopic ==  thisNodeFullName) || (g_sPreselectTopic.indexOf(thisNodeFullName) == 0)) {          
              node.expanded = 1;
              node.selected = (g_sPreselectTopic == thisNodeFullName);
            }
            else {
                node.expanded = (g_nDefaultExpandLevel == 0) || (node.getLevel() < g_nDefaultExpandLevel);
            }
        }
        // NJ 2008-04-10 Change end
        else {
            node.expanded = (g_nDefaultExpandLevel == 0) || (node.getLevel() < g_nDefaultExpandLevel);
        }
	}
}

function createTopicTreeHTML(node) {
	var res = "";
	var sChildNodesHTML = "";

	for (var i = 0; i < node.children.length; i++) {
		sChildNodesHTML += createTopicTreeHTML(node.children[i]);
	}

	var sMenuItemStyle = (node.selected ? "topicTreeMenuItemSelected" : "topicTreeMenuItem");
	var sMenuItemFolderStyle = (node.selected ? "topicTreeFolderImageSelected" : "topicTreeFolderImage");
	var sMenuItemExpandCollapseStyle = (node.hasChildren() ? (node.expanded ? "topicTreeFolderToggleExpanded" : "topicTreeFolderToggleCollapsed") : "topicTreeFolderToggleNone");
	var sExpandCollapsCell = '<td id="oTopicTreeMenuItemExpandCollapseImage' + node.id + '" class="' + sMenuItemExpandCollapseStyle + '"';
	if (node.hasChildren()) {
		sExpandCollapsCell += 'onclick="toggleTopicNodeChildren(' + node.id + ')" ';
	}
	var nIndentWidth = g_nChildNodeIndent;
	if (node.isRoot()) 
		nIndentWidth = 0;
	else if (node.parent.isRoot()) 
		nIndentWidth = g_nFirstLevelIndent;
	sExpandCollapsCell += ' nowrap>&nbsp;</td>';
	res += 
		'<table cellpadding=0 cellspacing=0>' +
			'<tr>' +
				'<td nowrap width="' + nIndentWidth + '"></td>' +
				'<td>' +
					'<table  cellpadding=0 cellspacing=0>' +
						'<tr>' +
							(!node.isRoot() ? sExpandCollapsCell : '') +
							'<td id="oTopicTreeMenuItemFolderImage' + node.id + '" class="' + sMenuItemFolderStyle + '" nowrap></td>' +
							'<td>' +
								'<table id="oTopicTreeMenuItem' + node.id + '" cellpadding=0 cellspacing=0 class="' + sMenuItemStyle + '" ' +
										'onmouseover="this.className=\'topicTreeMenuItemHover\'" ' +
										'onmouseout="this.className=\'' + sMenuItemStyle + '\'" ' +
										'onclick="selectTopicNode(' + node.id + ')">' +
									'<tr><td nowrap title="' + node.topicName + '">' + node.topicName + '</td></tr>' +
								'</table>' +
							'</td>' + 
						'</tr>' +
					'</table>' +
					'<div id="oTopicTreeMenuItemExpandCollapseArea' + node.id + '" style="display:' + (node.expanded ? "block" : "none") + '">' +
						sChildNodesHTML + 
					'</div>' +
				'</td>' +
			'</tr>' + 
		'</table>';
	
	return res;
}

function getTopicNodeArray(node) {
	var arrTopicNodes = new Array();
	getTopicNodeArrayRecursive(node, arrTopicNodes);
	return arrTopicNodes;
}

function getTopicNodeArrayRecursive(node, arrTopicNodes) {
	arrTopicNodes[arrTopicNodes.length] = node;
	for (var i = 0; i < node.children.length; i++) {
		getTopicNodeArrayRecursive(node.children[i], arrTopicNodes);
	}
}

function getTopicNodeFromID(node, id) {
	if (node.id == id) 
		return node;
	var res = null;
	for (var i = 0; i < node.children.length; i++) {
		res = getTopicNodeFromID(node.children[i], id);
		if (res != null)
			return res;
	}
	return null;
}

function selectTopicNode(nodeID) {
	var node = getTopicNodeFromID(g_oTopicTree, nodeID);
	updateSelectedTopicNode(nodeID);
	try {
		onTopicTreeSelect(node.id, node.topicPath, node);
	}
	catch (e) {
	}
}

function setClassName(obj, name) {
	if (obj.className != name)
		obj.className = name;
}

function updateSelectedTopicNode(nodeID) {
	var arrTopicNodes = getTopicNodeArray(g_oTopicTree);
	for (var i = 0; i < arrTopicNodes.length; i++) 
	{
		var node = arrTopicNodes[i];
		var oMenuItem = document.getElementById("oTopicTreeMenuItem" + node.id);
		var oMenuItemFolderImage = document.getElementById("oTopicTreeMenuItemFolderImage" + node.id);
		
		if (node.id == nodeID) {
			node.selected = true;
			setClassName(oMenuItem, "topicTreeMenuItemSelected");
			oMenuItem.onmouseout = function() { this.className="topicTreeMenuItemSelected"; }
			setClassName(oMenuItemFolderImage, "topicTreeFolderImageSelected"); 
		}
		else {
			node.selected = false;
			setClassName(oMenuItem, "topicTreeMenuItem");
			oMenuItem.onmouseout = function() { this.className="topicTreeMenuItem"; }
			setClassName(oMenuItemFolderImage, "topicTreeFolderImage");
		}
	}
}

function toggleTopicNodeChildren(nodeID) {
	var node = getTopicNodeFromID(g_oTopicTree, nodeID);
	node.expanded = !node.expanded;
	
	var oTopicTreeMenuItemExpandCollapseArea = document.getElementById("oTopicTreeMenuItemExpandCollapseArea" + node.id);
	oTopicTreeMenuItemExpandCollapseArea.style.display = (node.expanded ? "block" : "none");

	var oTopicTreeMenuItemExpandCollapseImage = document.getElementById("oTopicTreeMenuItemExpandCollapseImage" + node.id);
	oTopicTreeMenuItemExpandCollapseImage.className = (node.expanded ? "topicTreeFolderToggleExpanded" : "topicTreeFolderToggleCollapsed");
}

function selectTopicIndex(selectedTopicIndex) 
{
	updateSelectedTopic(selectedTopicIndex);

	var sTopicName = selectedTopicIndex == -1 ? "" : g_arrTopicNames[selectedTopicIndex];
	if (g_sRootTopic != "") {
		if (sTopicName != "")
			sTopicName = g_sRootTopic + "/" + sTopicName;
		else
			sTopicName = g_sRootTopic;
	}

	g_SelectedTopicIndex = selectedTopicIndex;


	try {
		onTopicTreeSelect(selectedTopicIndex, sTopicName);
	}
	catch (e) {
	}
}

function updateSelectedTopic(selectedTopicIndex) 
{
	for (var i = -1; i < g_arrTopicNames.length; i++) 
	{
		// 0 is the All Topics item
		var menuItemIndex = i + 1;
		var oMenuItem = document.getElementById("oTopicTreeMenuItem" + menuItemIndex);
		var oMenuItemFolderImage = document.getElementById("oTopicTreeMenuItemFolderImage" + menuItemIndex);
		
		if (i == selectedTopicIndex) { 
			setClassName(oMenuItem, "topicTreeMenuItemSelected");
			oMenuItem.onmouseout = function() { this.className="topicTreeMenuItemSelected"; }
			setClassName(oMenuItemFolderImage, "topicTreeFolderImageSelected");
		}
		else {
			setClassName(oMenuItem, "topicTreeMenuItem");
			oMenuItem.onmouseout = function() { this.className="topicTreeMenuItem"; }
			setClassName(oMenuItemFolderImage, "topicTreeFolderImage");
		}
	}
}

function getCurrentTopicPath()
{
	return selectedIndex == -1 ? "" : g_arrTopicNames[g_SelectedTopicIndex];
}

// -------------------------------------------------------------------------
// End of topic tree functions
// -------------------------------------------------------------------------

// -------------------------------------------------------------------------
// TopicNode class
// -------------------------------------------------------------------------

var g_nTopicIDCounter = 0;
function TopicNode(sTopicName, sTopicPath) {
	this.topicName = sTopicName;
	this.topicPath = sTopicPath;
	// Add the root topic (if specified) to the topic path
	// sTopicPath does not contain the root
	if (g_sRootTopic != "") {
		if (this.topicPath != "")
			this.topicPath = g_sRootTopic + "/" + this.topicPath;
		else
			this.topicPath = g_sRootTopic;
	}
	
	this.id = g_nTopicIDCounter++;
	this.selected = false;
	this.expanded = true;
	this.tableRow = null;
	this.children = new Array();
	this.parent = null;
	this.hasChildren = TopicNode_hasChildren;
	this.isRoot = TopicNode_isRoot;
	this.getLevel = TopicNode_getLevel;
	this.topicPaths = new Array(); // Allows for multiple topic names
	this.getTopicPaths = TopicNode_getTopicPaths;
}
function TopicNode_hasChildren() {
	return this.children.length > 0;
}
function TopicNode_isRoot() {
	return this.parent == null;
}
function TopicNode_getLevel() {
	var res = 0;
	var node = this;
	while (node.parent != null) {
		res++;
		node = node.parent;
	}
	return res;
}
function TopicNode_getTopicPaths() {
	if (!this.topicPaths || (this.topicPaths.length == 0)) {
		var res = new Array();
		res[res.length] = this.topicPath; 
		return res;
	}
	return this.topicPaths;
}

// -------------------------------------------------------------------------
// TopicNameObject class
// -------------------------------------------------------------------------

function TopicNameObject(sDisplayName, sTopicName) {
	this.displayName = sDisplayName;
	this.topicName = sTopicName;
}

