//
// HDView2.js    copyright 2009, Microsoft Corporation
//
// This script contains helper functions for initializing the HD View
// control.  Currently HD View is supported on IE, Firefox, Flock, Netscape,
// and Safari under Windows.
// For many users you should be able to just directly link to this 
// script on the HD View web site:
//   <script type="text/javascript" src="http://research.microsoft.com/en-us/um/redmond/groups/IVM/HDView/HDView2.js"></script>
// There are several advantages to this, including that bug fixes can
// be made in one common location and that if the control version changes
// this script will prompt users that an update is available.
// 
// For users who need to add functionality, you may modify this script and 
// use it on your own site.
// 
function hdvHelperFn()
{
	// variables that determine the platform
	var ua   = navigator.userAgent;
	var appv = navigator.appVersion;
	var isIE      = ( ua.indexOf( "MSIE" ) != -1 );
	var isFF      = ( ua.indexOf( "Firefox" ) != -1 ||  // also true for Flock, Netscape
					  ua.indexOf( "Safari" ) != -1 );
	var isVista   = ( ua.indexOf("Windows NT 6") != -1 );
	var isXP_2003 = ( (ua.indexOf("Windows NT 5.1") != -1 || 
					   ua.indexOf("Windows NT 5.2") != -1) );
	var isWin64 = (appv.indexOf("WOW64") != -1 || appv.indexOf("Win64") != -1);

	// number of names generated for global event handlers
	var handlerCount = 0;
	
	// public functions
	this.getMimeType = function() { return "application/x-hdview";} 
	this.getClsid    = function() { return "F81FB289-0FB6-4FE0-A488-101447EE1ED3"; }
	this.getCodepath = function() { return "http://research.microsoft.com/en-us/um/redmond/groups/IVM/HDView/"; }
	this.getSLpath   = function() { return "http://research.microsoft.com/en-us/um/redmond/groups/IVM/HDViewSL/"; }
	this.getVersion  = function() { return "3,2,0,0";  }
	this.isIE        = function() { return isIE; }
	this.isPlatformSupported = function() { return((isIE || isFF) && (isXP_2003 || isVista)) } 
	this.isHDViewInstalled = function()
	{
		var installed = false;
		try
		{
			reqVersionArray = this.getVersion().split(',');
			if( isIE ) {
				var hdvCntrl = new ActiveXObject("HDView.HDViewControl");
				if( hdvCntrl ) {
					controlVersionArray = hdvCntrl.Version.split('.');
					installed = reqVersionArray[0] < controlVersionArray[0] ||
								(reqVersionArray[0] == controlVersionArray[0] && 
								 reqVersionArray[1] <= controlVersionArray[1]);
				}
			}
			else {
				navigator.plugins.refresh(false);
				var hdvPlugin = navigator.plugins["HD View"];
				if( hdvPlugin ) {
					pluginVersionArray = hdvPlugin.description.split('.');
					installed = reqVersionArray[0] < pluginVersionArray[0] ||
								(reqVersionArray[0] == pluginVersionArray[0] && 
								 reqVersionArray[1] <= pluginVersionArray[1]);
				}
			}
		}
		catch (e) {}
		return installed;
	}
	this.addWindowEvent = function(eventName, func) {
		var oldHandler = window[eventName];
		if (typeof oldHandler != "function") {
			window[eventName] = func;
		}
		else {
			window[eventName] = function() {
				oldHandler();
				func();
			}
		}
	}
	this.generateHandlerName = function(handler) {
		var handlerName = null;
		if (typeof handler == "string") {
			handlerName = handler;
		}
		else if (typeof handler == "function") {
			if (handlerCount == 0) {
				this.addWindowEvent("onunload", cleanupGeneratedHandlers);
			}
			var count = handlerCount++;
			handlerName = "__hdvEvent" + count;
			window[handlerName] = handler;
		}
		return handlerName;
	}
	
	// private functions
	function cleanupGeneratedHandlers() {
		for (var i = handlerCount - 1; i >= 0; i--) {
			window["__hdvEvent" + i] = null;
		}
		handlerCount = 0;
	}
};
if (!window.hdvHelper) {
	window.hdvHelper = new hdvHelperFn();
}

function hdvHost(id, elementId, width, height, href, args, allowAbsoluteUrl)
{	
	// public functions
	this.setArgs             = setArgs;
	this.setProperty         = setProperty;
	this.getProperty         = getProperty;
	this.permalinkPopUp      = permalinkPopUp;

	// store the constructor arguments
	var argId        = id;
	var argElementId = elementId;
	var argWidth     = width;
	var argHeight    = height;
	var argHref      = href; 
	var argArgs      = args;
	var argAllowAbsoluteUrl = allowAbsoluteUrl;

	var hdvControl = null;
	var propertyHolder = null;
	var deferredProperties = {};
	var curFilename = "";
	var currentViewer = 0; // 0 = HDView only, 1 = DeepZoom only, 2 = Dual

	//
	// the "constructor"
	//
	// synopsis: If this is not a supported platform this function writes
	//           some html into the page to that effect.  Otherwise it 
	//           first detects if the control is installed on this machine.
	//           If it is not installed then some html is written into the
	//           page that offers users a link to the install page.  If it is 
	//           installed, then the control will be embedded in the supplied 
	//           'elementId'.
	// 

	constructor();

	function constructor()
	{
		setArgs(argArgs);
		var parent = document.getElementById(argElementId);
		if ( currentViewer == 1 || (currentViewer == 2 && !hdvHelper.isPlatformSupported()) ) {
			parent.innerHTML = buildHTMLForSilverlight(argId, argWidth, argHeight);
			hdvControl = document.getElementById(argId);
		}
		else if ( !hdvHelper.isPlatformSupported() ) {
			parent.innerHTML = buildHTMLForNotSupported();
		}
		else if ( !hdvHelper.isHDViewInstalled() ) {
			parent.innerHTML = buildHTMLForInstall();
		}
		else {
			parent.innerHTML = buildHTMLForControl(argId, argWidth, argHeight);
			hdvControl = document.getElementById(argId);
			propertyHolder = hdvControl;
			setDeferredProperties();
		}
	}

	// other functions
	function setArgs(argString)
	{
		var args = argString.split('&');
		for (var i = 0; i < args.length; i++) {
			var arg = args[i];
			var index = arg.indexOf("=");
			var prop = arg.substr(0, index);
			var val = arg.substr(index + 1);
			if (prop.length > 0 && val.length > 0) {
				if (prop == "Viewer") {
					if (!hdvControl) {
						currentViewer = val;
					}
				}
				else {
					setProperty(prop, val);
				}
			}
		}
	}

	function setProperty(prop, val)
	{
		// If we don't yet have a target to set the property on,
		// just remember the property and value for later.
		if (!propertyHolder) {
			deferredProperties[prop] = val;
		}
		else {
			if( prop == "FileName" ) {
				val = unescape(val);
				curFilename = val;
				if (val.charAt(0) == '#')
				{
					val = val.substring(1, val.length);
					val = document.getElementById(val).text;
				}
				else
				{
					if ( !argAllowAbsoluteUrl )
					{
						var pageArgs = argHref.split('?');
						var pagePath = pageArgs[0].substring(0, pageArgs[0].lastIndexOf('/') + 1);
						val = pagePath + val;
					}
				}
			}

			// Determine local decimal point representation and format
			// the val correctly under IE, Firefox uses "." regardless.
			if( prop == "FOV" || prop == "Yaw" || prop == "Pitch" ||
				prop == "Zoom" || prop == "XCtr" || prop == "YCtr" )
			{
				val = val.toString(); // allow a number or a string
				var separator = Number(1.1).toLocaleString().charAt(1);
				val = val.replace('/\\' + separator + '/', '.');
			}

			if( prop == "BackgroundColor" || prop ==  "ForegroundColor" )
				val = parseInt(val);

			propertyHolder[prop] = val;
		}
	}

	function getProperty(prop)
	{
		if( propertyHolder ) {
			return propertyHolder[prop];
		}
	}

	//
	// function: permalinkPopUp
	//
	// synopsis: call this function to create a pop-up window that contains
	//           a 'permalink' url for the current control view parameters.  
	//           The user is prompted to copy the url to the clipboard.
	//           
	function permalinkPopUp()
	{
		if ( hdvControl )
		{
			win = window.open("", "", "width=450, height=180"); 
			win.document.open(); 
			win.document.write('<html><head><title>HD View</title></head><body>');
			win.document.write('<div align="center">');

			var pageArgs = argHref.split('?');
			var pagePath = pageArgs[0].substring(0, pageArgs[0].lastIndexOf('/') + 1);

			var escfile   = escape(curFilename);
			var permafile = "FileName=" + escfile; 
			var embedfile = "FileName=" + (!argAllowAbsoluteUrl ? pagePath : "") + escfile;
			if (curFilename.charAt(0) == '#')
			{
				var embedxml = document.getElementById(curFilename.substring(1, curFilename.length));
				// convert tabs to spaces for spaces.live.com
				var xmltext = embedxml.text.replace(/\t/g, ' ').replace(/\s+/g, ' ');
				if (hdvHelper.isIE())
					embedxml = embedxml.XMLDocument;
				else
					embedxml = new DOMParser().parseFromString(xmltext.substr(xmltext.indexOf("?>") + 2), "text/xml");
				
				var imageset = embedxml.getElementsByTagName("imageset");
				if (imageset.length > 0)
				{
					// need to fix up relative path if any
					imageset = imageset[0].attributes;

					// check for relative path (not url or root)
					var embedurl = imageset.getNamedItem("url");
					if (embedurl.value.indexOf("https://") < 0 &&
						embedurl.value.indexOf("http://") < 0 &&
						embedurl.value.indexOf("file://") < 0 &&
						embedurl.value.indexOf("ftp://")  < 0 &&
						embedurl.value.charAt(0) != '/' &&
						embedurl.value.charAt(0) != '\\' &&
						embedurl.value.charAt(1) != ':')
					{
						embedurl.value = pagePath + embedurl.value;

						xmltext = '<?xml version="1.0"?>\r\n<root>\r\n  <imageset\r\n';
						for (var i = 0; i < imageset.length; i++)
							xmltext += '    ' + imageset[i].name + '=\"' + imageset[i].value + '\"\r\n';
						xmltext += '  />\r\n</root>\r\n';
					}
				}

				embedfile = "FileName=" + escape(xmltext);
			}

			var permalinkargs;
			var fov = getProperty('FOV');
			if (fov > 0)
				permalinkargs =
							"&FOV=" + Math.round(fov * 1000) / 1000 +
							"&Yaw=" + Math.round(getProperty('Yaw') * 1000) / 1000 +
							"&Pitch=" + Math.round(getProperty('Pitch') * 1000) / 1000;
			else
				permalinkargs =
							"&Zoom=" + Math.round(getProperty('Zoom') * 1000) / 1000 +
							"&XCtr=" + Math.round(getProperty('XCtr') * 1000000) / 1000000 +
							"&YCtr=" + Math.round(getProperty('YCtr') * 1000000) / 1000000;
			var panMode = getProperty("PanMode");
			if (panMode != 0)
				permalinkargs += "&PanMode=" + panMode;
			var toneMode = getProperty("ToneMode");
			if (toneMode != 0)
				permalinkargs += "&ToneMode=" + toneMode;
			var projMode = getProperty("ProjMode");
			if (projMode != 0)
				permalinkargs += "&ProjMode=" + projMode;
			var backgroundColor = getProperty("BackgroundColor");
			if (backgroundColor != 0x000000)
				permalinkargs += "&BackgroundColor=0x" + backgroundColor.toString(16);
			var foregroundColor = getProperty("ForegroundColor");
			if (foregroundColor < 0)
				foregroundColor += 0x100000000;  // work around bug in older HD View versions
			if (foregroundColor != 0xFFFFFF00)
				permalinkargs += "&ForegroundColor=0x" + foregroundColor.toString(16);
			if (currentViewer != 0)
				permalinkargs += "&Viewer=" + currentViewer;

			win.document.write('<form id=LinkForm name=LinkForm>');
			win.document.write('Link to paste in email or IM:<br/><input type="text" id="PermaLink" size="50" value="' +
				pageArgs[0] + '?' + permafile + permalinkargs + '" contentEditable="false" onclick="select()"/><br/><br/>');

			permalinkargs = permalinkargs.replace(/&/g, '&amp;amp;');	// encode for HTML
			var iframe = "<iframe style='width: 400px; height: 300px; margin: 0' frameborder='0' src='" +
				"http://silverlight.services.live.com/invoke/63450/HDView/iframe.html?" + embedfile + permalinkargs + "'></iframe>";
			win.document.write('HTML to embed in web site:<br/><input type="text" id="IFrame" size="50" value="' +
				iframe + '" contentEditable="false" onclick="select()"/><br/><br/>');
			win.document.write('</form>');

			win.document.write('</div></body></html>');
			win.document.close();   
		}
	}

	function buildHTMLForInstall()
	{
		var style1 = 'align="center" style="color:white; width: 500px; background-color:#404040"';
		var style2 = 'style="text-align:center; font-size:x-large; font-weight:bold"';
		var style3 = 'font-size:medium';

		var imgInstall = '"' + hdvHelper.getCodepath() + 'images/HDInstall.jpg"';
		var pageInstall = '"' + hdvHelper.getCodepath() + 'HDInstall.htm"';
		
		if (document.body.clientWidth < 500)
		{
			style1 = 'align="center" style="color:white; width: 240px; background-color:#404040"';
			style2 = 'style="text-align:center; font-size:medium; font-weight:bold"';
			style3 = 'font-size:small';
			imgInstall = '"' + hdvHelper.getCodepath() + 'images/HDInstall2.jpg"';
		}

		var reqVersionArray = hdvHelper.getVersion().split(',');
		
		// create an install message
		var html = "";
		html += '<table ' + style1 + '>';
		html += '<tr><td ' + style2 +'>HD View Beta ' + reqVersionArray[0] + '.' + reqVersionArray[1] + ' needs to be installed.</td></tr>';
		html += '<tr><td style="text-align:center; ' + style3 + '"><br/>';
		html += '<a href=' + pageInstall + ' target="_top"><img alt="GOTO INSTALL" src=' + imgInstall + '/><br/><br/></td></tr></a>';
		html += '<tr><td style="' + style3 + '"><em>If you have already installed Beta ' + reqVersionArray[0] + '.' + reqVersionArray[1] + ' and you still see this message, ';
		html += 'then you need to restart your browser.</em><br/></tr></td>';
		html += '</table>';

		return html;
	}

	function buildHTMLForControl(id, width, height)
	{
		var html = "";
		html += '<object id="' + id + '"';
		html += ' type="' + hdvHelper.getMimeType() + '"';
		html += ' width="' + width + '"';
		html += ' height="' + height + '"';
		html += '></object>';

		return html;
	}

	function buildHTMLForSilverlight(id, width, height)
	{
		// Generate a unique global function name for the Silverlight plugin loaded handler for this instance.
		var handlerName = hdvHelper.generateHandlerName(silverlightPluginLoaded);

		var html = '';

		html += '<object id="' + id + '"';
		html += ' data="data:application/x-silverlight," type="application/x-silverlight-2" width="' + width + '" height="' + height + '">';
		html += '<param name="minRuntimeVersion" value="2.0.31005.0"/>';
		html += '<param name="autoUpgrade" value="true"/>';
		html += '<param name="enableHtmlAccess" value="true"/>';
		html += '<param name="source" value="HDViewSL.xap"/>';
		html += '<param name="background" value="black"/>';
		html += '<param name="initParams" value="InitializationCompleted=' + handlerName + '"/>';

		html += '<div style="text-align:center;font-family:Arial;margin-top:50px;">';
		html += 'This page requires Silverlight 2.<br />';
		html += '<br />';
		html += '<a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">';
		html += '<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>';
		html += '</a>';
		html += '</div>';
		html += '</object>';

		return html;
	}

	function buildHTMLForNotSupported()
	{
		var html = "";
		html += '<br><br><p style="color:#FF9933; font-size:large;">';
		html += 'Sorry the HD View Beta is not supported on this platform.'
		html += '  Must be Internet Explorer, Firefox, Flock, Netscape, or Safari on Windows XP, Server 2003, or Vista.'
		html += '</p><br>';

		return html;
	}

	function silverlightPluginLoaded() {
		propertyHolder = hdvControl.content.settings;
		setDeferredProperties();
	}
	
	function setDeferredProperties() {
		for (var prop in deferredProperties) {
			setProperty(prop, deferredProperties[prop]);
		}
		deferredProperties = {};
	}
}
