
/* Global Variables */
var cisXML = "cis.xml";
var NODE_ELEMENT = 1;
var cisVT = "vt", cisSS = "ss";

/*
Fucntion: selectNodes()
Notes:    Used to mimic IE selectNodes method. This is added to the appropraite objects
Arguments:
	xpath   (an xpath expression)
*/
function selectNodes(xpath)
{
	var resultNodes = this.ownerDocument.evaluate(xpath, this, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

	var nodeArray = new Array();
	for (n = 0; n < resultNodes.snapshotLength; n++ )
	{
		nodeArray[n] = resultNodes.snapshotItem(n);
	}

	return nodeArray;
}

/*
Fucntion:selectSingleNodes()
Notes:    Used to mimic IE selectSingleNode method. This is added to the appropraite objects
Arguments:
	xpath   (an xpath expression)
*/
function selectSingleNode(xpath)
{
	return this.ownerDocument.evaluate(xpath, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

/*
Fucntion: loadXML()
Notes:    Loads an XML file and returns an XML Document object
Arguments:
	xmlfile (the url of the xml file)
*/
function loadXML(xmlfile)
{
	// intialise variables
	var xmlDoc;

	// Check supported XML functions
	if (window.ActiveXObject)
	{
		// Load XML document
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = false;
		xmlDoc.load(xmlfile);

		// check for error when loading XML file
		if (xmlDoc.parseError.errorCode != 0)
		{
			document.write("XML File Load Error\nCode: " + xmlDoc.parseError.errorCode + "\nReason: " + xmlDoc.parseError.reason);
		}
	}
	else if (window.XMLHttpRequest)
	{
		// load XML file
		var xmlRequest = new XMLHttpRequest();
		xmlRequest.open("GET", xmlfile, false);
		xmlRequest.send(null);

		// set xmlDoc to XML tree
		xmlDoc = xmlRequest.responseXML;

		// confirm browser support
		if (document.evaluate && Element)
		{
			// extend Element object to support selectNodes and selectSingleNode functions
			Element.prototype.selectNodes = selectNodes;
			Element.prototype.selectSingleNode = selectSingleNode;
		}
	}
	else
	{
		// need to decide what to do in this situation
		document.write("NO XML LOAD SUPPORT");
	}

	// we are not using the onload event as Opera does not seem to support it when using asyncronous loading
	// this method works for IE5+, FF1+, Opera 8+, Netscape 7+ and Safari 1.3+
	return xmlDoc;
}

/*
Object: viewer()
Notes:  Creates an instance of a viewer object used to store related data
Arguments:
	none
*/
function viewer(rootNode, viewerId)
{
	// intialise default properties
	this.id = viewerId;
	this.projectName = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='name']");
	this.name = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/name");
	this.image = new Array();

	switch (viewerId.toLowerCase())
	{
	case cisVT:
		this.getViewer(rootNode);
		this.getLinks(rootNode);
		//this.getEaf(rootNode);
		this.getMenu(rootNode);
		this.getVTControls(rootNode);
		break;
	

	case cisSS:
		this.getViewer(rootNode);
		this.getLinks(rootNode);
		//this.getEaf(rootNode);
		this.getMenu(rootNode);
		this.getAssociatedViewer(rootNode);
		this.getSSInfoPanel(rootNode);
		this.getIPControls(rootNode);
		break;
	
	}
}

viewer.prototype.getViewer = function(rootNode)
{
	this.viewer = new Array();
	this.viewer.size = new size(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='size']");
	this.viewer.windowTitle = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='windowTitle']");
	this.viewer.viewerTitle = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='viewerTitle']");
	this.viewer.logo = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='logo']");
	this.viewer.titleFont = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='titleFont']");
	this.viewer.titleColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='titleColour']");
	this.viewer.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='backgroundColour']");
	this.viewer.backgroundImage = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='backgroundImage']");
	this.viewer.borderColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='borderColour']");
	this.viewer.borderWidth = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='viewer']/setting[@id='borderWidth']/value");
}

viewer.prototype.getLinks = function(rootNode)
{
	this.links = new Array();
	this.links.font = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='links']/setting[@id='font']");
	this.links.colour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='links']/setting[@id='colour']");
	this.links.hoverColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='links']/setting[@id='hoverColour']");
	this.links.underline = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='links']/setting[@id='underline']/value");
}

//viewer.prototype.getEaf = function(rootNode)
//{
//	this.eaf = new Array();
//	this.eaf.display = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='eaf']/setting[@id='display']/value");
//	this.eaf.subjectLine = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='eaf']/setting[@id='subjectLine']");
//}

viewer.prototype.getMenu = function(rootNode)
{
	this.menu = new Array();
	this.menu.font = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='menu']/setting[@id='font']");
	this.menu.colour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='menu']/setting[@id='colour']");
	this.menu.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='menu']/setting[@id='backgroundColour']");
}

viewer.prototype.getAssociatedViewer = function(rootNode)
{
	this.associatedviewer = new Array();
	this.associatedviewer.viewer = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='associateviewer']/setting[@id='viewer']/value");
	this.associatedviewer.linkText = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='associateviewer']/setting[@id='linkText']");
	this.associatedviewer.size = new size(rootNode, "//viewer[@id='" + this.associatedviewer.viewer + "']/settings/category[@id='viewer']/setting[@id='size']");
}

viewer.prototype.getDisclaimer = function(rootNode)
{
	this.disclaimer = new Array();
	this.disclaimer.font = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='font']");
	this.disclaimer.colour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='colour']");
	this.disclaimer.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='backgroundColour']");
	this.disclaimer.borderColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='borderColour']");
	this.disclaimer.borderWidth = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='borderWidth']/value");
	this.disclaimer.text = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='disclaimer']/setting[@id='text']");
}

viewer.prototype.getVTControls = function(rootNode)
{
	this.vtcontrols = new Array();
	this.vtcontrols.autoSpinSpeed = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='autoSpinSpeed']/value");
	this.vtcontrols.fov = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='fov']/value");
	this.vtcontrols.fovmin = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='fovmin']/value");
	this.vtcontrols.fovmax = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='fovmax']/value");
	this.vtcontrols.navigationBar = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='navigationBar']/value");
	this.vtcontrols.panSpinSpeed = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='panSpinSpeed']/value");
	this.vtcontrols.cursor = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='cursor']/value");
	this.vtcontrols.loadingScreenImage = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='vtcontrols']/setting[@id='loadingScreenImage']");
}

viewer.prototype.getPBInfoPanel = function(rootNode)
{
	this.infopanel = new Array();
	this.infopanel.titleFont = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='pbinfopanel']/setting[@id='titleFont']");
	this.infopanel.titleColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='pbinfopanel']/setting[@id='titleColour']");
	this.infopanel.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='pbinfopanel']/setting[@id='backgroundColour']");
	this.infopanel.borderColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='pbinfopanel']/setting[@id='borderColour']");
	this.infopanel.borderWidth = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='pbinfopanel']/setting[@id='borderWidth']/value");
}
viewer.prototype.getSSInfoPanel = function(rootNode)
{
	this.infopanel = new Array();
	this.infopanel.titleFont = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='titleFont']");
	this.infopanel.titleColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='titleColour']");
	this.infopanel.font = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='font']");
	this.infopanel.colour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='colour']");
	this.infopanel.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='backgroundColour']");
	this.infopanel.borderColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='borderColour']");
	this.infopanel.borderWidth = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ssinfopanel']/setting[@id='borderWidth']/value");
}

viewer.prototype.getIPControls = function(rootNode)
{
	this.ipcontrols = new Array();
	this.ipcontrols.font = new font(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='font']");
	this.ipcontrols.colour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='colour']");
	this.ipcontrols.backgroundColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='backgroundColour']");
	this.ipcontrols.borderColour = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='borderColour']");
	this.ipcontrols.borderWidth = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='borderWidth']/value");
	this.ipcontrols.autoPlay = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='autoPlay']/value");
	this.ipcontrols.autoPlayInterval = getNodeData(rootNode, "//viewer[@id='" + this.id + "']/settings/category[@id='ipcontrols']/setting[@id='autoPlayInterval']");
}

function projectSettings(rootNode)
{
	this.name = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='name']");
	this.logo = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='logo']");
	this.titleFont = new font(rootNode, "//project/settings/category[@id='project']/setting[@id='titleFont']");
	this.titleColour = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='titleColour']");
	this.backgroundColour = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='backgroundColour']");
	this.backgroundImage = getNodeData(rootNode, "//project/settings/category[@id='project']/setting[@id='backgroundImage']");
	this.links = new Array();
	this.links.font = new font(rootNode, "//project/settings/category[@id='links']/setting[@id='font']");
	this.links.colour = getNodeData(rootNode, "//project/settings/category[@id='links']/setting[@id='colour']");
	this.links.hoverColour = getNodeData(rootNode, "//project/settings/category[@id='links']/setting[@id='hoverColour']");
	this.links.underline = getNodeData(rootNode, "//project/settings/category[@id='links']/setting[@id='underline']/value");
}

function font(rootNode, xPath, viewerId)
{
	this.family = getNodeData(rootNode, xPath + "/family");
	this.size = getNodeData(rootNode, xPath + "/size");
	this.bold = getNodeData(rootNode, xPath + "/bold");
	this.italic = getNodeData(rootNode, xPath + "/italic");
}

function size(rootNode, xPath, viewerId)
{
	// get value from xml file
	var xmlValue = getNodeData(rootNode, xPath + "/value");
	var values = xmlValue.split(",");
	this.width = values[0];
	this.height = values[1];
}


function getNodeData(rootNode, xPath)
{
	// initialise variables
	var data = "";
	var prefix = new Array();

	if (xPath.indexOf("//viewer") > -1)
	{
		prefix[0] = xPath.replace(/\/\/viewer.+?\//i, "//common/");     //   \/\/?.+?\//i, "//common/");
		prefix[1] = xPath.replace(/\/\/viewer([\[|\/])/i, "//viewers/viewer$1");
	}
	else
		prefix[0] = xPath;

	// search for settings
	for (p = 0; p < prefix.length; p++)
	{
		// check browser functionality
		if (window.ActiveXObject || document.evaluate)
			var xmlNode = rootNode.selectSingleNode(prefix[p]);
		else
			var xmlNode = getNode(rootNode, prefix[p]);
		
		// check if node contains data
		if (xmlNode != null)
		{
			if (xmlNode.childNodes.length > 0)
				data = xmlNode.firstChild.nodeValue;
		}
	}

	// return data found (if any)
	return unescape(data);
}

function xPathToRegExp(xPath)
{
	// initialise pattern strings
	var patterns = new Array(4);
	for (i = 0; i < patterns.length; i++)
		patterns[i] = new Array(2);
	
	patterns[0][0] = /\/\/?([\w-]+)/ig;
	patterns[0][1] = "<$1>";
	patterns[1][0] = /<([\w-]+>)(\[@[\w-]+\s*=\s*['|"][\w-]+['|"]\])?$/ig;
	patterns[1][1] = "<$1$2([\\s\\S]*?)</$1";
	patterns[2][0] = />\[@([\w]+)=['|"]([\w\s-]+)['"]\]/ig;
	patterns[2][1] = "\\s*$1\=['|\"]$2['|\"]\\s*>";
	patterns[3][0] = /></ig;
	patterns[3][1] = ">[\\s\\S]*?<";

	// convert xPath into regular expression pattern
	var xPathPattern = xPath;
	for (i = 0; i < patterns.length; i++)
		xPathPattern = xPathPattern.replace(patterns[i][0], patterns[i][1]);

	// return regular expression pattern
	return xPathPattern;
}

function getNode(rootNode, xPath)
{
	// set variables
	var foundNode = false;
	var xmlNode = null;

	// search for each node in list
	var rePattern = /([\w-]+)(?:\[@(.*?)=['|"](.*?)['|"]\])?/ig;
	var xPathSteps = xPath.match(rePattern);
	for (step = 0; step < xPathSteps.length; step++)
	{
		// split xPath step in parts
		var rePattern = /([\w-]+)(?:\[@(.*?)=['|"](.*?)['|"]\])?/i;
		var stepParts = xPathSteps[step].match(rePattern);
		if (stepParts.length > 0)
			var nodeName = stepParts[1], attribName = stepParts[2], attribValue = stepParts[3];
		else
			var nodeName = "", attribName = "", attribValue = "";

		// reset flag
		foundNode = false;

		// enumerate each childNode
		for (node = 0; node < rootNode.childNodes.length; node++)
		{
			// check if current node matches node name
			var currentNode = rootNode.childNodes[node];
			if (currentNode.nodeName == nodeName)
			{
				// check for any attribute
				if (attribName != undefined)
				{
					if (currentNode.getAttribute(attribName) == attribValue)
					{
						foundNode = true;
						break;
					}
				}
				else
				{
					// found node, set flag and exit loop
					foundNode = true;
					break;
				}
			}
		}

		// check if node was found
		if (foundNode)
		{
			// store current node and set root ready for next loop
			xmlNode = currentNode;
			rootNode = currentNode;
		}
		else
		{
			// node not found so exit loop and return null
			xmlNode = null;
			break;
		}
	}

	// return result
	return xmlNode;
}

function getProjectXML(defaultXML)
{
	var projectXML = getPageSetting("xml");
	if (projectXML == "")
		projectXML = defaultXML;

	// return result
	return projectXML;
}

function getPageSetting(settingName)
{
	// set default result string
	var settingValue = "";

	// get search string of document
	var settings = document.location.search;
	if (settings.length > 0)
	{
		// get setting
		var reSetting = new RegExp(settingName + "=([^&]+)", "i");
		var matches = settings.match(reSetting);
		if (matches != null)
			var settingValue = matches[1];
	}

	//return project xml
	return settingValue;
}



// Open link if not being run within CIS
function openLink(strURL, strWinName, intWidth, intHeight, strSettings)
{
	// Check if viewer is being run within CIS
	if (inCIS())
	{
		//Inform user that link will only work outside of CIS
		alert('This hyperlink is disabled within CIS.', 0 + 64, "Hyperlink Disabled");
		var blnReturn = false;
	}
	else
	{
		// Check if window name was specified
		if (strWinName == "") { strWinName = "_blank"; }

		// Open link
		window.open(strURL, strWinName, "width=" + intWidth + ",height=" + intHeight + "," + strSettings);
		var blnReturn = true;
	}
	// Return value
	return blnReturn;
}

// check if page is loaded within CIS
function inCIS()
{
	// Check if viewer is being run within CIS
	var cis = false;
	if ((window.parent.frames.length > 0) && (window.parent.document.title == "CIS Viewer Preview"))
		cis = true;

	// return value
	return cis;
}

//Open viewer in appropriate sized windows and center on screen
function openViewer(viewerRef, baseURL, viewerWidth, viewerHeight, openCenter)
{
	// Initialise defaults
	var showScrollBars = "no";

	// Check screen height
	if (screen.height)
	{
		// set viewer height dependant on screen height
		var maxViewerHeight = (screen.height / 5 ) * 4;
		if (viewerHeight > maxViewerHeight)
		{
			showScrollBars = "yes";
			viewerHeight = maxViewerHeight;
			viewerWidth = viewerWidth + 20;
		}
	}

	//Get center co-ordinates
	var leftPos = (screen.width && openCenter) ? "left=" + ((screen.width - viewerWidth) / 2) : "";
	var topPos = (screen.height && openCenter) ? "top=" + ((screen.height - viewerHeight) /2) : "";

	// Open viewer
	var viewerURL = baseURL + viewerRef + "/" + viewerRef + ".html";
	openLink(viewerURL, "", viewerWidth, viewerHeight, leftPos + "," + topPos + ",resizeable=0,scrollbars=" + showScrollBars);
}

function convertToHTML(value)
{
	// convert text value to HTML
	var rePattern = /&lt;(.+?)&gt;/ig;
	var convertedValue = value.replace(rePattern, "<$1>");
	return convertedValue;
}

