// VARIABLES LOADED FROM SETTINGS FILE
var ColumnCount;
var ColumnWidth;
var TargetNode;
var ConnectionStyle;
var ConnectionColor;
var MajorGroupStyle;
var MinorGroupStyle;
var SiteLinkStyle;
var MajorGroupImage;
var MinorGroupImage;
var SiteLinkImage;
var BackgroundColor;

// GLOBAL VARIABLES
var ParentNode;
var SiteMapNodesHTML;
var innerHTMLString = "";
var SectionIndex;
var SiblingIndex = 0;
var PreviousDepth = 0;
var RunningSiblingIndex = 0;
var ChildCount = 0;

// HTML RENDERING VARIABLES
var SiteLinkSymbol = "<div style='z-index:10;background:url(%SITELINKIMAGE%) no-repeat;position:absolute;overflow:hidden;width:16px;height:18px;top:%TOP%px;left:%LEFT%px'></div>"
var MinorGroupSymbol = "<div style='z-index:10;background:url(%MINORGROUPIMAGE%) no-repeat;position:absolute;overflow:hidden;width:16px;height:18px;top:%TOP%px;left:%LEFT%px'></div>"
var MajorGroupSymbol = "<div style='z-index:10;background:url(%MAJORGROUPIMAGE%) no-repeat;position:absolute;overflow:hidden;width:16px;height:18px;top:%TOP%px;left:%LEFT%px'></div>"
var ParentWrapper = "<div style='position:absolute;overflow:hidden;height:18px;width:%COLUMNWIDTH%px;top:%TOP%px;left:%LEFT%px;%MAJORGROUPSTYLE%'>%TITLE%</div>"
var GroupWrapper = "<div style='position:absolute;overflow:hidden;height:18px;width:%COLUMNWIDTH%px;top:%TOP%px;left:%LEFT%px;%MINORGROUPSTYLE%'>%TITLE%</div>"
var LinkWrapper = "<div style='position:absolute;overflow:hidden;height:18px;width:%COLUMNWIDTH%px;top:%TOP%px;left:%LEFT%px;%SITELINKSTYLE%'>%TITLE%</div>"
var ConnectionLayer = "<div style='z-index:0;position:absolute;overflow:hidden;height:%HEIGHT%px;width:%WIDTH%px;top:%TOP%px;left:%LEFT%px;border-left-style:%CONNECTIONSTYLE%;border-bottom-style:%CONNECTIONSTYLE%;border-width:1px;border-color:%CONNECTIONCOLOR%'></div>"

function getColumnWidth()
{
    return ColumnWidth;
}
// Loads the settings from the XML file and stores them in the allotted variables
function loadSettings()
{
	var Settings = xmlDoc.getElementsByTagName('settings');
	for (i=0;i<Settings[0].childNodes.length;i++)
	{
		if (Settings[0].childNodes[i].nodeType == 1) 
		{			
			switch (Settings[0].childNodes[i].nodeName)
			{
				case('columnCount') :
				{
					ColumnCount = parseInt(Settings[0].childNodes[i].firstChild.nodeValue);break;
				}
				case('columnWidth') :
				{
					ColumnWidth = parseInt(Settings[0].childNodes[i].firstChild.nodeValue);break;
				}
				case('targetLayerId') :
				{
					TargetNodeId = Settings[0].childNodes[i].firstChild.nodeValue;
					TargetNode = document.getElementById(TargetNodeId);					
					break;
				}				
				case('connectionStyle') :
				{
					ConnectionStyle = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('connectionColor') :
				{
					ConnectionColor = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('majorGroupStyle') :
				{
					MajorGroupStyle = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('minorGroupStyle') :
				{
					MinorGroupStyle = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('siteLinkStyle') :
				{
					SiteLinkStyle = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('majorGroupImage') :
				{
					MajorGroupImage = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('minorGroupImage') :
				{
					MinorGroupImage = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('siteLinkImage') :
				{
					SiteLinkImage = Settings[0].childNodes[i].firstChild.nodeValue;					
					break;
				}	
				case('backgroundColor') :
				{
					BackgroundColor = "#fff2f9";					
					break;
				}	
			}			
		}
	}
} 

// Main function that loads site map
function loadSiteMap()
{
	// Read XML file for Mozilla clients
	if (document.implementation && document.implementation.createDocument)
	{
		xmlDoc = document.implementation.createDocument("","",null);
		xmlDoc.onload=drawMap;
	}
	// Read XML file for Internet Explorer clients
	else if (window.ActiveXObject)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.onreadystatechange = function()
		{
			if (xmlDoc.readyState == 4) drawMap()
		};
	}
	else
	{
		//Browser does not support XML handling
		return;
	}
	xmlDoc.load("sitemap.xml");
}

// Function to obtain a node's depth within the site tree
function getDepth(Node)
{
	Depth = 0;
	CurrentNode = Node;
	while (CurrentNode != ParentNode)
	{
		CurrentNode = CurrentNode.parentNode;
		Depth++;
	}
	return Depth;
}

// Function to obtain a node's visual depth within the site tree
function getExpandedPosition(Node)
{
	if (Node.nodeType == 1) 
	{
  	var PrecedingSiblings = 0;
  	var CurrentNodeParent = Node.parentNode;  	
  	for (m=0;m<CurrentNodeParent.childNodes.length;m++)
  	{				  	  		
  		if (CurrentNodeParent.childNodes[m].nodeType == 1)
  		{    			
  			if (CurrentNodeParent.childNodes[m] == Node)
  				break;
  			ChildCount = 0;
  			
  			if (CurrentNodeParent.childNodes[m].hasChildNodes())
  				getTotalChildCount(CurrentNodeParent.childNodes[m]);
  			
  			PrecedingSiblings+=ChildCount + 1;
  		}
  	}
	
		return PrecedingSiblings;
	}
	else
		return 0;
}

// Gets the number of children a node has recursing children-bearing child nodes
function getTotalChildCount(Node)
{		
	if (Node.hasChildNodes() == false)
	  return;	
	if (Node.nodeType == 1) 
	{
  	if (Node.hasChildNodes() && Node.getAttribute('title') != null) 
  	{			  	
  		ChildCount+=getProperNodeCount(Node);
  		for (j=0;j<Node.childNodes.length;j++)
  		{
  			if (Node.childNodes[j].nodeType == 1)
  			{			  				
  				if (Node.childNodes[j].hasChildNodes() && Node.childNodes[j].getAttribute('title') != null)
  					getTotalChildCount(Node.childNodes[j]);
  			}
  		}
  	}	
	}
	else 
		return;
}

// Gets the number of child nodes that are of type element
function getProperNodeCount(Node)
{
	var ProperNodeCount = 0;
	for (i=0;i<Node.childNodes.length;i++)
  {
  	if (Node.childNodes[i].nodeType == 1)
  	  ProperNodeCount++;
  }
  return ProperNodeCount;
}

// Gets the total amount of children for a group
function getGroupChildCounts(Node)
{	
	var ChildCounts = new Array(getProperNodeCount(Node));	
	var ProperNodeIndex = 0;
	for (k=0;k<Node.childNodes.length;k++)
	{
		if (Node.childNodes[k].nodeType == 1) 
		{
  		if (Node.childNodes[k].getAttribute('title') != null) 
  		{						
  			ChildCount = 0;
  			getTotalChildCount(Node.childNodes[k]);
  			ChildCounts[ProperNodeIndex] = ChildCount;					
  			ProperNodeIndex++;
  		}
		}
	}
	return ChildCounts;
}

// Renders the HTML for the site map and stores the major group nodes in an array
function drawSiteMapNode(CurrentTreeNode, CurrentDisplayNode)
{	
	if (CurrentTreeNode.parentNode == ParentNode)
		SiblingIndex = 0;
	else
		SiblingIndex = getExpandedPosition(CurrentTreeNode);

	if (CurrentTreeNode != ParentNode) 
	{		
		var TopOffset	= ((1 + SiblingIndex) * 18);
		var ImageTopOffset	= 0;
		var LeftOffset = 16;
		var ImageLeftOffset = 0;
		var LinkTopOffset = 2;
		var LinkLeftOffset = 20;
		var CurrentSymbol;
		var CurrentLinkWrapper;
		
		if (CurrentTreeNode.parentNode != ParentNode)
		{
		    var LinkTop = (((CurrentTreeNode.parentNode.parentNode != ParentNode) ? (getExpandedPosition(CurrentTreeNode.parentNode) + 0) : 1) * 18) - 8;
		    var LinkLeft = (((CurrentTreeNode.parentNode.parentNode != ParentNode) ? (getDepth(CurrentTreeNode) - 3) : 0) * 16) + 8;
		    var LinkWidth = 16;
		    var LinkHeight = (getExpandedPosition(CurrentTreeNode) + 1) * 18;
		    innerHTMLString += ConnectionLayer.replace("%TOP%",LinkTop).replace("%LEFT%",LinkLeft).replace("%WIDTH%",LinkWidth).replace("%HEIGHT%",LinkHeight).replace("%CONNECTIONSTYLE%",ConnectionStyle).replace("%CONNECTIONSTYLE%",ConnectionStyle).replace("%CONNECTIONCOLOR%",ConnectionColor);
		}
		
		if (CurrentTreeNode.parentNode == ParentNode) 
		{
			CurrentSymbol = MajorGroupSymbol.replace('%TOP%', ImageTopOffset).replace('%LEFT%',ImageLeftOffset).replace("%MAJORGROUPIMAGE%", MajorGroupImage);
			if (CurrentTreeNode.getAttribute('url') == null)
				CurrentLinkWrapper = ParentWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', CurrentTreeNode.getAttribute('title')).replace("%MAJORGROUPSTYLE%",MajorGroupStyle).replace("%COLUMNWIDTH%",(ColumnWidth - 20));
			else
				CurrentLinkWrapper = ParentWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', "<a href=\"" + CurrentTreeNode.getAttribute('url') + "\" style=\"" + MajorGroupStyle + "\">" + CurrentTreeNode.getAttribute('title') + "</a>").replace("%MAJORGROUPSTYLE%",MajorGroupStyle).replace("%COLUMNWIDTH%",(ColumnWidth - 20));
		}
		else if (CurrentTreeNode.hasChildNodes() == false)
		{
			CurrentSymbol = SiteLinkSymbol.replace('%TOP%', ImageTopOffset).replace('%LEFT%',ImageLeftOffset).replace("%SITELINKIMAGE%", SiteLinkImage);
			if (CurrentTreeNode.getAttribute('url') == null)
				CurrentLinkWrapper = LinkWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', CurrentTreeNode.getAttribute('title')).replace("%SITELINKSTYLE%",SiteLinkStyle).replace("%COLUMNWIDTH%",(ColumnWidth - 20));
			else
				CurrentLinkWrapper = LinkWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', "<a href=\"" + CurrentTreeNode.getAttribute('url') + "\" style=\"" + SiteLinkStyle + "\">" + CurrentTreeNode.getAttribute('title') + "</a>").replace("%SITELINKSTYLE%",SiteLinkStyle).replace("%COLUMNWIDTH%",(ColumnWidth - 20));
		}
		else
		{
			CurrentSymbol = MinorGroupSymbol.replace('%TOP%', ImageTopOffset).replace('%LEFT%',ImageLeftOffset).replace("%MINORGROUPIMAGE%", MinorGroupImage);		
			if (CurrentTreeNode.getAttribute('url') == null)
				CurrentLinkWrapper = GroupWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', CurrentTreeNode.getAttribute('title')).replace("%MINORGROUPSTYLE%",MinorGroupStyle).replace("%COLUMNWIDTH%",(ColumnWidth - 20)).replace("%COLUMNWIDTH%",(ColumnWidth - 20));
			else
				CurrentLinkWrapper = GroupWrapper.replace('%TOP%', LinkTopOffset).replace('%LEFT%', LinkLeftOffset).replace('%TITLE%', "<a href=\"" + CurrentTreeNode.getAttribute('url') + "\" style=\"" + MinorGroupStyle + "\">" + CurrentTreeNode.getAttribute('title') + "</a>").replace("%MINORGROUPSTYLE%",MinorGroupStyle);
		}
		 
		if (CurrentTreeNode.parentNode == ParentNode)
			innerHTMLString += "<div" + " style='font-family:arial;font-size:11px;position:absolute;display:inline;height:20px;top:" + 
			"%TOP%" + "px" + ";left:" + "%LEFT%" + "px'>" + CurrentSymbol + CurrentLinkWrapper;
		else
			innerHTMLString += "<div" + " style='font-family:arial;font-size:11px;position:absolute;display:inline;height:20px;top:" + 
			TopOffset + "px" + ";left:" + LeftOffset + "px'>" + CurrentSymbol + CurrentLinkWrapper;										
			
		SiblingIndex++;
		RunningSiblingIndex++;
	}
	
	if (CurrentTreeNode.hasChildNodes()) 
	{
  	var i = 0;
  	for (i=0;i<CurrentTreeNode.childNodes.length;i++)
  	{
  		if (CurrentTreeNode.childNodes[i].nodeType == 1) 
  		drawSiteMapNode(CurrentTreeNode.childNodes[i], CurrentDisplayNode);
  	}
	}
	
	if (CurrentTreeNode != ParentNode)
		innerHTMLString += "</div>";
	if (CurrentTreeNode.parentNode == ParentNode) 
	{
		SiteMapNodesHTML[SectionIndex] = innerHTMLString;
		innerHTMLString="";
		SectionIndex++;
		SiblingIndex = 0;
		RunningSiblingIndex = 0;
	}	  
}

// Get Max Column Height
function getMaxColumnHeight(Columns)
{
	if (ColumnCount == 1)
		return Columns[0];
	else
	{
		var MaxColumnHeight = 0;
		for (colIndex = 0; colIndex < Columns.length; colIndex++)
		{
			if (Columns[colIndex] > MaxColumnHeight)
				MaxColumnHeight = Columns[colIndex];
		}
		return MaxColumnHeight;
	}	
}

// Centers the site map on the page
function CenterSiteMap() 
{
    SiteMapLeft = (document.body.clientWidth - (ColumnWidth * ColumnCount)) / 2;            
    document.getElementById("SiteMap").style.left = SiteMapLeft + "px";
    document.getElementById("SiteMap").style.top = "50px";
}

// Renders the site map
function drawMap()
{
	// Load Settings
	loadSettings();			
	// Set Target Layer Style
	TargetNode.style.position = 'relative';		
	TargetNode.style.textAlign = 'left';
	TargetNode.style.backgroundColor = BackgroundColor;
	TargetNode.style.width = (ColumnWidth * ColumnCount) + 'px';	
	//TargetNode.style.height = '300px';
  var SiteMapNodes = xmlDoc.getElementsByTagName('siteMapNode'); 
  ParentNode = SiteMapNodes[0]; 
  var ValidNodesCount = 0; 
  for (i=0;i<ParentNode.childNodes.length;i++)
  {
  	if (ParentNode.childNodes[i].nodeType == 1)
  	  ValidNodesCount++;
  }
  SiteMapNodesHTML = new Array(ValidNodesCount);
  SectionIndex = 0;
  drawSiteMapNode(SiteMapNodes[0], TargetNode);  
  var ItemsPerColumn = Math.floor(ValidNodesCount / ColumnCount);    
  var ExtraItems = ValidNodesCount % ColumnCount;  
  var DIVBody = "";
  var NextColumn = false;
  var ColShift = 0;
  var TopOffset = 4;
  var LeftOffset = 4;  
  var GroupChildCounts = getGroupChildCounts(ParentNode); 
  var ColumnHeights = new Array(ColumnCount);
  var ColumnIndex = 0;
  var ColumnHeightSum = 0;  
  for (i=0;i<SiteMapNodesHTML.length;i++)
  {   	 	
  	if (NextColumn)
  	{
  		LeftOffset += ColumnWidth;
  		TopOffset = 4;
  		ColumnHeights[ColumnIndex] = ColumnHeightSum + 4;  	
  		ColumnIndex++;	
  		ColumnHeightSum = 0;
  		NextColumn = false;  		
  	}  	
  	else if (i>0)
  	{  		  		  	
  		TopOffset += 20 + ((GroupChildCounts[i-1] + 1) * 18);
  	}  	
  	DIVBody += SiteMapNodesHTML[i].replace("%LEFT%",LeftOffset).replace("%TOP%",TopOffset);
  	ColumnHeightSum += (((NextColumn) || (i==0)) ? 4 : 20) + ((GroupChildCounts[i] + 1) * 18); 
  	if (((i+1+ColShift) % ItemsPerColumn == 0) && (ExtraItems == 0))
  		NextColumn = true;
  	else if (ExtraItems > 0)
  	{
  		if ((i+1) % (ItemsPerColumn + 1) == 0)
  		{
  			NextColumn = true;
  			ColShift++;
  			ExtraItems--;
  		}
  	}  	  	
  } 
  ColumnHeights[ColumnIndex] = ColumnHeightSum;  	
  var sColumnHeights = ""; 
  for (i=0;i<ColumnHeights.length;i++)
  {
  	sColumnHeights += ColumnHeights[i] + ',';
  }
  TargetNode.style.height = getMaxColumnHeight(ColumnHeights) + 'px';  
  TargetNode.innerHTML = DIVBody;    
}