/**
* @overview This library contains all the client side detection functionality
* @uses lib/Sureflix/Sureflix.js
* @uses lib/Prototype/Prototype.js
* @uses lib/Sureflix/Utilities/Utils.js
* @uses lib/Sureflix/Plugins/Plugins.js
* @uses lib/Sureflix/Error/ErrorHandler.js
* @uses ClientServerBridge.asp
*/

/**
 * @class This class contains client site browser and plugin detection functionality.
 * @property {String} browser The browser's name: Firefox, Explorer, Safari, etc. or Unknown
 * @property {Float} version The browser's version or Unknown
 * @property {String} OS The operating system's name: Windows, Mac, Linux, etc. or Unknown
 */
Sureflix.Plugins.Detector = {
	browser:	null,
	version:	null,
	OS:			null
}


// shorthand
SxDt = Sureflix.Plugins.Detector;


/**
* enumeration of platforms, which map to plugins depending on the OS and Browser
*/
Sureflix.Plugins.Detector.platforms = {
	RealPlayer: "r",
	WindowsMedia: "w",
	Silverlight: "s",
	Flash: "f"
}
	
	
/**
* enumeration of plugins
*/
Sureflix.Plugins.Detector.pluginNames = {
	windowsMediaFirefox: "Windows Media Player Firefox",
	windowsMedia: "Windows Media Player",
	windowsMediaFlip4Mac: "Flip4Mac Windows Media",
	realPlayer: "RealPlayer",
	silverlight: "Silverlight",
	flash: "Shockwave Flash",
	director: "Shockwave Director"
}

/**
* enumeration of plugins
*/
Sureflix.Plugins.Detector.requiredVersions = {
	windowsMediaFirefox: "1.0",
	windowsMedia: "9.0",
	windowsMediaFlip4Mac: "2.2",
	realPlayer: "6.0.6.131",
	silverlight: "3.0.40624.0",
	flash: "9.0.115.0", // required to watch H.264
	director: "9.0"
}


/**
 * Returns true if the specified platform is supported on the current operating system and browser (regardless if it's actually installed)
 * @param {Sureflix.Plugins.Detector.platforms} platform The video platform in question
 * @return {Boolean} Returns true if the specified platform is supported
 */
Sureflix.Plugins.Detector.isPlatformSupported = function(platform) {
	switch (platform) {
		case this.platforms["RealPlayer"]:
			return this.isRealPlayerSupported();
			break;
		case this.platforms["WindowsMedia"]:
			return this.isWindowsMediaSupported();
			break;
		case this.platforms["Silverlight"]:
			return this.isSilverlightSupported();
			break;
		case this.platforms["Flash"]:
			return this.isFlashSupported();
			break;
		default:
			return false;
	}
}


/**
 * Returns true if the required version of a plugin that supports the specified platform is installed
 * @param {Sureflix.Plugins.Detector.platforms} platform The video platform in question
 * @return {Boolean} Returns true if the specified platform is installed
 */
Sureflix.Plugins.Detector.isRequiredPlatformInstalled = function(platform) {
	switch (platform) {
		case this.platforms["RealPlayer"]:
			return this.isRequiredRealPlayerInstalled();
			break;
		case this.platforms["WindowsMedia"]:
			return this.isRequiredWindowsMediaInstalled();
			break;
		case this.platforms["Silverlight"]:
			return this.isRequiredSilverlightInstalled();
			break;
		case this.platforms["Flash"]:
			return this.isRequiredFlashInstalled();
			break;
		default:
			return false;
	}
}


/**
* Returns true if the given plugin is installed in the browser
* This is internal only
* @param {String} pluginName The name of the plugin
* @return {Boolean} True if detected, false if it's not
*/
Sureflix.Plugins.Detector.isNavigatorPluginInstalled = function (pluginName) {
	if (navigator.plugins && navigator.plugins.length){
		navigator.plugins.refresh();
		for (var i=0; i < navigator.plugins.length; i++) {
			var n = navigator.plugins[i].name;
			if ( n != null && n.indexOf(pluginName) > -1 ) {
				return true;
			}
		}
	}
	return false;
}


/**
* Returns the version number of the given plugin extracted from the plugin description
* This is internal only
* @param {Sureflix.Plugins.Detector.pluginsNames} pluginName The name of the plugin
* @return {String} The version string or false if the plugin is not detected
*/
Sureflix.Plugins.Detector.getNavigatorPluginVersion = function (pluginName) {
	if (navigator.plugins && navigator.plugins.length){
		navigator.plugins.refresh();
		for (var i=0; i < navigator.plugins.length; i++) {
			var iName = navigator.plugins[i].name;
			if (iName != null && iName.indexOf(pluginName) > -1) {
				var version = navigator.plugins[i].description;
				// 4 in Flip4Mac interferes with version detection
				version = version.replace(/Flip4Mac/g, ""); 
				version = version.replace(/[^0-9.,]/g, "");
				if (version == "" || version == ".") {
					version = navigator.plugins[i].name;
					// 4 in Flip4Mac interferes with version detection
					version = version.replace(/Flip4Mac/g, "");
					version = version.replace(/[^0-9.,]/g, "");
				}
				if (version == "" || version == ".") {
					// if no version number, we'll assume 1.0
					version = "1.0";
				}
				return version;
			}
		}
	}
	return false;
}


/**
 * Compares two version string in the format "0.0.0.0"
 * @example var isRequired = Sureflix.Plugins.Detector.isRequiredVersion("3.5", "3.5.0.12")  //true
 * @example var isRequired = Sureflix.Plugins.Detector.isRequiredVersion("3.5", "3.4.25.19")  //false
 * @param {String} requiredVersion A string with the minimum required version
 * @param {String} detectedVersion A string with the detected version
 * @returns {Boolean} Returns true if the detectedVersion if equal to or higher than the requiredVersion
 */
Sureflix.Plugins.Detector.isRequiredVersion = function(requiredVersion, detectedVersion) {
	if (!requiredVersion || SxUt.isEmpty(requiredVersion)) {
		requiredVersion = "0";
	}
	if (!detectedVersion || SxUt.isEmpty(detectedVersion)) {
		detectedVersion = "0";
	}
	var requiredParts = requiredVersion.split(".");
	var detectedParts = detectedVersion.split(".");
	
	for (var i=0; i<requiredParts.length; i++) {
		if (i > detectedParts.length-1) {
			detectedParts[i] = "0";
		}
		if (parseInt(detectedParts[i]) > parseInt(requiredParts[i])) {
			break;
		} else if (parseInt(detectedParts[i]) < parseInt(requiredParts[i])) {
			return false;
		} else {
			continue;
		}
	}
	
	return true;
}


/**
 * Returns info about the RealPlayer plugin or ActiveX object
 * @return {Object} plugin, pluginName, version, requiredVersion
 */
Sureflix.Plugins.Detector.getRealPlayerInfo = function() {
	var plugin = "realPlayer";
	var version = false;

	if (window.ActiveXObject) {
		var definedControls = [
	        'rmocx.RealPlayer G2 Control',
	        'rmocx.RealPlayer G2 Control.1',
	        'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
	        'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
	        'RealPlayer'
	    ];

		var control = null;
		for (var i = 0; i < definedControls.length; i++) {
			try {
				control = new ActiveXObject(definedControls[i]);
			} catch (e) {
				continue;
			}
			if (control) {
				break;
			}
		}
		if (control) {
			try {
				version = control.GetVersionInfo();
			} catch (e) {
				version = "";
			}
			control = null;
		}
	} else {
		this.detectBrowser();
		if (this.OS == "Mac") {
			version = this.getNavigatorPluginVersion("RealPlayer");
			if (version) {
				version = this.requiredVersions.realPlayer;
			}
		} else {
			version = this.getNavigatorPluginVersion("RealPlayer Version");
		}
	}

	return {
		plugin: plugin,
		pluginName: this.pluginNames[plugin],
		version: version,
		requiredVersion: this.requiredVersions[plugin]
	};
}


/**
 * Returns true if the required version of RealPlayer is installed
 * @return {Boolean} Returns true if the RealPlayer version is equal to or higher than this.requiredVersions.realPlayer
 */
Sureflix.Plugins.Detector.isRequiredRealPlayerInstalled = function() {
	var RMOKOverride = Sureflix.Utilities.GetCookie("RMOKOverride").toLowerCase();

	if (RMOKOverride == "true") {
		return true;
	} else if(RMOKOverride == "false"){
		return false;
	} else {
		var detectedInfo = this.getRealPlayerInfo();
		return this.isRequiredVersion(detectedInfo.requiredVersion, detectedInfo.version);
	}
}


/**
 * Returns true if RealPlayer is supported on the current operating system and browser (regardless if it's actually installed)
 */
Sureflix.Plugins.Detector.isRealPlayerSupported = function() {
	this.detectBrowser();
	if (this.browser == "Safari" && (this.isSilverlightSupported() || this.isWindowsMediaSupported())) {
		return false;
	} else {
		return true;
	}
}


/**
 * Returns info about the Windows Media plugin or ActiveX object
 * @return {Object} plugin, pluginName, version, requiredVersion
 */
Sureflix.Plugins.Detector.getWindowsMediaInfo = function() {
	var plugin = "windowsMedia";
	var version = false;

	if (window.ActiveXObject) {
		var control = null;
		try {
			control = new ActiveXObject('WMPlayer.OCX');
		}
		catch (e) {
			return false;
		}
		if (control) {
			version = control.versionInfo;
			control = null;
		}
	} else {
		this.detectBrowser();
		if ((this.browser == "Firefox" || this.browser == "Safari") && this.OS == "Windows") {
			plugin = "windowsMediaFirefox";
		}
		version = this.getNavigatorPluginVersion(this.pluginNames[plugin]);
	}

	return {
		plugin: plugin,
		pluginName: this.pluginNames[plugin],
		version: version,
		requiredVersion: this.requiredVersions[plugin]
	};
}


/**
* Returns true if the required version of Windows Media is installed
* @return {Boolean} Returns true if the WM version is equal to or higher than this.requiredVersions.windowsMedia
*/
Sureflix.Plugins.Detector.isRequiredWindowsMediaInstalled = function() {
	var WMOKOverride = Sureflix.Utilities.GetCookie("WMOKOverride").toLowerCase();

	if (WMOKOverride == "true") {
		return true;
	} else if (WMOKOverride == "false") {
		return false;
	} else {
		var detectedInfo = this.getWindowsMediaInfo();
		return this.isRequiredVersion(detectedInfo.requiredVersion, detectedInfo.version);
	}
}


/**
* Returns true if Windows Media is supported on the current operating system and browser (regardless if it's actually installed)
*/
Sureflix.Plugins.Detector.isWindowsMediaSupported = function() {
	this.detectBrowser();
	if (this.OS == "Mac") {
		return false;
	} else if (this.browser == "Firefox") {
		return false;
	} else {
		return true;
	}
}


/**
* Returns info about the Silverlight plugin
* @return {Object} plugin, pluginName, version, requiredVersion
*/
Sureflix.Plugins.Detector.getSilverlightInfo = function() {
	var plugin = "silverlight";
	var version = false;

	if (window.ActiveXObject) {
		try {
			var control = new ActiveXObject('AgControl.AgControl');
			if (control) {
				var versions = [this.requiredVersions.silverlight, "2.0", "1.1", "1.0"];
				for (i = 0; i < versions.length; i++) {
					if (control.isVersionSupported(versions[i])) {
						version = versions[i];
						break;
					}
				}
				
				control = null;
			}
		} catch (e) {
			version = false;
		}
	} else {
		version = this.getNavigatorPluginVersion(this.pluginNames[plugin]);
	}

	return {
		plugin: plugin,
		pluginName: this.pluginNames[plugin],
		version: version,
		requiredVersion: this.requiredVersions[plugin]
	};
}


/**
* Returns true to allow the automated Silverlight installation process to take place
* @return {Boolean} Always returns true
*/
Sureflix.Plugins.Detector.isRequiredSilverlightInstalled = function() {
	return true;
}


/**
* Returns true if Silverlight is supported on the current operating system and browser (regardless if it's actually installed)
*/
Sureflix.Plugins.Detector.isSilverlightSupported = function() {
	//return Silverlight.supportedUserAgent(this.requiredVersions.silverlight, navigator.userAgent);
	//supportedUserAgent() does not work correctly when 2.0.31005.0	is passed as the version
	return Silverlight.supportedUserAgent("2.0", navigator.userAgent);}


/**
* Downloads and Installs the current version of Silverlight
*/
Sureflix.Plugins.Detector.getCurrentSilverlight = function() {
	Silverlight.getSilverlight(this.requiredVersions["silverlight"]);}

/**
* Downloads and Installs the current version of Flash
*/
Sureflix.Plugins.Detector.getCurrentFlash = function() {
    window.open("http://get.adobe.com/flashplayer/", 'Flash', "menubar=1,resizable=1,width=900,height=900"); 
}

/**
* Returns info about the Windows Media plugin or ActiveX object
* @return {Object} plugin, pluginName, version, requiredVersion
*/
Sureflix.Plugins.Detector.getFlashInfo = function() {
	var plugin = "flash";
	var version = false;
	
	if (window.ActiveXObject) {
		try {
			var control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
			if (control) {
				version = control.GetVariable('$version').substring(4);
				version = version.split(',');
				version = version[0] + '.' + version[1];
			}
		} catch (e) {
			version = false;
		}
	} else {
		version = this.getNavigatorPluginVersion(this.pluginNames[plugin]);
	}

	return {
		plugin: plugin,
		pluginName: this.pluginNames[plugin],
		version: version,
		requiredVersion: this.requiredVersions[plugin]
	};
}


/**
 * Returns true if the required version of Flash is installed
 * @return {Boolean} Returns true if Flash is installed
 */
Sureflix.Plugins.Detector.isRequiredFlashInstalled = function (){
	var FMOKOverride = Sureflix.Utilities.GetCookie("FMOKOverride").toLowerCase();

	if (FMOKOverride == "true") {
		return true;
	} else if(FMOKOverride == "false") {
		return false;
	} else {
		var detectedInfo = this.getFlashInfo();
		return this.isRequiredVersion(detectedInfo.requiredVersion, detectedInfo.version);
	}
}


/**
* Returns true if Flash is supported on the current operating system and browser (regardless if it's actually installed)
*/
Sureflix.Plugins.Detector.isFlashSupported = function() {
	//Flash should be supported everywhere (except smart phones)
	return true;
}


/**
* Detects the browser and operating system, and sets the class's properties, which can then be accessed by you. 
*/
Sureflix.Plugins.Detector.detectBrowser = function () {
	//if brower is already defined, don't run this function again
	if (this.browser) {
		return;
	}
	
	this.browser = this.searchString(this.dataBrowser) || "Unknown";
	this.version = this.searchVersion(navigator.userAgent)
		|| this.searchVersion(navigator.appVersion)
		|| "Unknown";
	this.OS = this.searchString(this.dataOS) || "Unknown";
}


/**
 * Searches for the browser or OS (used internally).
 * @param {Object} data
 */
Sureflix.Plugins.Detector.searchString = function (data) {
	for (var i=0;i<data.length;i++)	{
		var dataString = data[i].string;
		var dataProp = data[i].prop;
		this.versionSearchString = data[i].versionSearch || data[i].identity;
		if (dataString) {
			if (dataString.indexOf(data[i].subString) != -1)
				return data[i].identity;
		}
		else if (dataProp)
			return data[i].identity;
	}
}


/**
 * Searches for the version (used internally).
 * @param {Object} data
 */

Sureflix.Plugins.Detector.searchVersion = function (dataString) {
	var index = dataString.indexOf(this.versionSearchString);
	if (index == -1) return;
	return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
}


/**
 * Array of pre-defined browser strings used by searchString (used internally).
 */
Sureflix.Plugins.Detector.dataBrowser = [
	{ 	string: navigator.userAgent,
		subString: "OmniWeb",
		versionSearch: "OmniWeb/",
		identity: "OmniWeb"
	},
	{
		string: navigator.vendor,
		subString: "Apple",
		identity: "Safari"
	},
	{
		prop: window.opera,
		identity: "Opera"
	},
	{
		string: navigator.vendor,
		subString: "iCab",
		identity: "iCab"
	},
	{
		string: navigator.vendor,
		subString: "KDE",
		identity: "Konqueror"
	},
	{
		string: navigator.userAgent,
		subString: "Firefox",
		identity: "Firefox"
	},
	{
		string: navigator.vendor,
		subString: "Camino",
		identity: "Camino"
	},
	{	// for newer Netscapes (6+)
		string: navigator.userAgent,
		subString: "Netscape",
		identity: "Netscape"
	},
	{
		string: navigator.userAgent,
		subString: "MSIE",
		identity: "Explorer",
		versionSearch: "MSIE"
	},
	{
		string: navigator.userAgent,
		subString: "Gecko",
		identity: "Mozilla",
		versionSearch: "rv"
	},
	{ 	// for older Netscapes (4-)
		string: navigator.userAgent,
		subString: "Mozilla",
		identity: "Netscape",
		versionSearch: "Mozilla"
	}
]


/**
 * Array of pre-defined OS strings used by searchString (used internally).
 */

Sureflix.Plugins.Detector.dataOS = [
	{
		string: navigator.platform,
		subString: "Win",
		identity: "Windows"
	},
	{
		string: navigator.platform,
		subString: "Mac",
		identity: "Mac"
	},
	{
		string: navigator.platform,
		subString: "Linux",
		identity: "Linux"
	}
]


/**
 * Returns true if cookies are enabled.
 */
Sureflix.Plugins.Detector.areCookiesEnabled = function () {

	function xDeleteCookie(name) {
		var oldDate = new Date(1970, 1, 1);
		document.cookie = x_cookieName + "=0; expires=" + oldDate.toGMTString();
	}
	
	//set cooke, then try to read cookie
	var x_cookieName = "xyzzy"; // unique

	var x_expires = new Date(); 
	x_expires.setFullYear(x_expires.getFullYear()+1); // testing persistent cookies
	xDeleteCookie(x_cookieName); // don't get false positive

	// add path if you want to. drop expires for session (non=persistent) cookie.
	document.cookie = x_cookieName + "=test";
	document.cookie.expires=" + x_expires.toGMTString() + ";

	// now look for it.
	var x_cookieString = document.cookie || "";
	var x_cookies = x_cookieString.split(/\s*;\s*/);
	var x_found = false;
	
	for (var i=0; i < x_cookies.length; i++) { // we can't use for - in loops with prototype (pg 25 in 1.5.1 manual)
		var cookie = x_cookies[i];
		if(cookie){
			var dough = cookie.split(/\s*=\s*/);
			if (dough[0] == x_cookieName) { x_found = true; break; }
		}
	}

	// ensure it's gone
	xDeleteCookie(x_cookieName);

	return x_found;
}

 
/**
 * Sets a cookie to override plugin detection
 * @param {String} media accepts 'R' or 'W' only, default to 'W'
 * @param {Boolean} isOK if the media is ok or not
 * @example	Sureflix.Plugins.Detector.setMediaOverride("W", true);
 * @author Amy 03/06/2008
 */
Sureflix.Plugins.Detector.setMediaOverride = function (media, isOK) {
	var wMedia = 'W';
	var rMedia = 'R';
	var expirationDate = new Date();
	expirationDate.setTime(expirationDate.getTime()+(1*24*60*60*1000));
	
	//convert to boolean
	isOK = !!(isOK);
	
	media = (media || wMedia).toString().toUpperCase();
	
	if (media != rMedia) {
		media = wMedia;
	}

	Sureflix.Utilities.SetCookie(media + "MOKOverride", (isOK + ""), expirationDate);
}