/*
	file:	        flashplayer.js
	description:	extends classes from base.js
	$Header: /source/docroot/downloadcenter/js/flashplayer.js,v 1.29 2010/01/25 20:56:03 rusliu Exp $

*/

/*
	file:	        base.js
	description:	base JS classes for download centers. to be extended by product specific files (i.e. flashplayer.js)
	$Header: /source/docroot/downloadcenter/js/base.js,v 1.29 2009/12/10 00:31:08 kfavro Exp $

*/

/* ********************
 * BASE CLASSES
 ******************** */

var Request = Class.create({
	// child classes must implement these empty functions
	initialize   :   function() {},
	getResultDisplay	:	function(eventname){ return displayResult; },
	getNoResultDisplay	: function(){return noResultDisplay},
	getAjaxUrl	:	function(){return url;},
	
	_onContinueClick   :   function(e) {
	
		var url = this.getAjaxUrl();
		
		// if the user has not made an OS selection, alert them and stop all event processing
		if ($F("select_os") == -1) {
			document.fire("display:noSelection");
			return;			
		} else {					
			// show ajax loading graphic for start of request
			$("ajaxloading").show();
			  
			// disable button until user selects from dropdown again
			Event.element(e).disabled = true;
				
			var options 	= {
				method 		: "get", 
				onSuccess 	: this._onFetchSuccess.bind(this),
				onFailure 	: this._onFetchFailure
			};
	
			new Ajax.Request(url, options);
		}
	},
	
	_onFetchSuccess   :   function(transport) {
		var json 			= transport.responseJSON;
		var eventname		= $F("eventname");
		var displayResult	= this.getResultDisplay(eventname);
		var noDisplayResult = this.getNoResultDisplay();
		
		if(json.length) {	
			document.fire(displayResult, json);
		} else {
			document.fire(noDisplayResult);
		}
	},
	
	_onFetchFailure   :   function() {
		var noDisplayResult = this.getNoResultDisplay();
		
		document.fire(noDisplayResult);	
	},
	
	prepareQueryString	   :   function() {
		var os				= $F("select_os");
		var eventname		= $F("eventname");
		var query_as		= this.fakeAgent[os];
		var query_string 	= "?";
		
		// enumerate over query_as and load query_string with key/values
		for(key in query_as) {
			query_string += key + "=" + query_as[key] + "&";
		}
		
		query_string += "eventname=" + eventname;

		return query_string;
	}
});

var Display = Class.create({
	
	// child classes must implement these empty functions
	getTemplate	:	function() { return template; },
	getTemplateProperties	:	function() {return template_properties},
	
	initialize	:	function() {
				
		showaddon = false;
		
		document.observe("display:otherversions", this._displayOtherVersions.bindAsEventListener(this));
		
		document.observe("display:noSelection", this._displayNoSelection.bindAsEventListener(this));
		
		document.observe("display:addons", this._displayAddons.bindAsEventListener(this));
		
		if($("addon")) $("addon").observe("click", this.updateTotalSize.bindAsEventListener(this));
		
		// if user is on step2 and changes their os/language preference, reset page		
		if($("select_os")) $("select_os").observe("change", this.curtainsDown);
		
		// event handler for "download now" button
        $("buttonDownload").observe("click", this._onDownloadClick.bindAsEventListener(this)); 
	},
	
	buildOffersTable   :   function(json) {
        try {
			var i, j;
			temp_obj = {};
			
			// start by removing any offers currently written to page
			$("offers_table").update();
			
			for (i = 0; i < json.length; i++) {
				var offer = json[i];
				var row, template, template_properties;
				
				// create our template
				template = this.getTemplate();
				
				// create our properties                                                  
				template_properties = this.getTemplateProperties(offer);
				
				// apply the properties to the template
				var row = template.evaluate(template_properties);
				
				// insert evaluated template into DOM
				$("offers_table").insert(row);
				
				// create temp object so we can later create event handlers
				// for each offer being inserted into the row
				temp_obj["offer" + offer.id] = this.buildItem(offer);
				
			}
			
			// gather up all radio buttons within our new table
			var radios = $$("#offers_table input[type=radio]");
			
			// iterate over each radio button
			radios.each(function(button, j){
				var item = temp_obj[button.id];
				var dlm_compatible_installer = item.dlm_compatible_installer;
				
				// set up click handler for each radio button
				button.observe("click", function(e){
				
					// initialize all rows by removing their hilite
					$$("#offers_table tr").each(function(row){
						row.removeClassName("selected");
					});
					
					utility.set_dlm_compatible_installer(dlm_compatible_installer);
					this.adjustofferbox(button, item);
				}.bind(this));
				
				// first row needs to be auto-selcted and have its
				// associated offer data appear offer box
				if (j == 0) {
					button.checked = true;
					
					utility.set_dlm_compatible_installer(dlm_compatible_installer);
					this.adjustofferbox(button, item);
				}
			}, this);
		}
		catch (e) {
			errorHandler (e);
		}
    },
	
	buildItem		:	function(offer) {
		var item = {
			size : offer.file_size, 
        	url : offer.systemreqs_url,
            dlm_compatible_installer : offer.can_use_dlm
		};
		
		return item;
	},
	
	curtainsUp   :   function() {
		$("ajaxloading").hide();
		$("step2").show();
	},
	
	curtainsDown   :   function() {
		try {
			$("buttonContinue").disabled = false;
			if($("error-message") && $("error-message").getStyle("display") != "none") $("error-message").hide();
			if($("step2") && $("step2").getStyle("display") != "none") $("step2").hide();	
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	updateTotalSize   :   function() {
		try {
			client 	= parseFloat(commaToDot($("clientfilesize").innerHTML));
	       	addon 	= parseFloat(commaToDot($("addonfilesize").innerHTML));
			rounded = Math.round((client + addon)*100)/100;
	
	        total	= $("totalfilesize");
			clientshow = (otherLocale()) ? dotToComma(client) : client;
	
			var addedUp;
			if($("addon").checked) {
				addedUp = (otherLocale()) ? dotToComma(rounded) : rounded;
				total.update(addedUp);
			} else{
				total.update(clientshow);
			}
			$("clientfilesize").update(clientshow); // update client file size, in order to show native decimal place for FR,DE,IT and ES locale
		}
			catch (e) {
				errorHandler (e);
		  }
	},	
        
    highlightandupdate   :   function(button, item) {
    	button.up("tr").addClassName("selected");
		item.size = (otherLocale()) ? dotToComma(item.size) : item.size;	
        $("clientfilesize").update(item.size);
		
    },
	
	adjustofferbox   :   function(button, item) {   
		// update size/requirements url and highlight selected row
        this.highlightandupdate(button, item);
		
        // make/hide addon offer
        this.makeaddonoffer();
		
        // update total size field based on state of addon offer checkbox
        this.updateTotalSize();
    },
	
	makeaddonoffer   :   function() {
		if(utility.dlm_compatible() && showaddon) {
			if(!$("addonoffers").visible()){
				$("addonoffers").show();
                $("addon").checked = true;
			}

        } else {
			$("addonoffers").hide();
			$("addon").checked = false;
        }
    }
});

var SwissArmyKnife = Class.create({

	initialize   :   function() {
		this.ua				= navigator.userAgent;
		
		// properties for specific browsers
		this.isIE6			= this.ua.match(/MSIE 6/) != null;
		this.isIE7 			= this.ua.match(/MSIE 7/) != null;
		this.isIE8 			= this.ua.match(/MSIE 8/) != null;
		this.is64bitIE 		= this.ua.match(/Win64|x64/) != null;
		this.is32IEonVista64= this.ua.match(/WOW64/) != null && this.isIE7;
		this.isFirefox 		= this.ua.match(/Firefox/) != null;
		this.isFirefox30 	= this.ua.match(/Firefox\/3/) != null;
		this.isFirefox20 	= this.ua.match(/Firefox\/2/) != null;
		this.isFirefox15 	= this.ua.match(/Firefox\/1\.5/) != null;
		this.gp_compat_ie	= this.isIE6 || this.isIE7 || this.isIE8;
		this.gp_compat_ff	= this.isFirefox30 || this.isFirefox20 || this.isFirefox15;
		this.gtbinstalled	= this.ua.match(/GTB/) != null;
				
		// properties for specific os/platforms
		this.isWinXP 		= this.ua.match(/Windows NT (5\.1)/) != null;
		this.isWinXPSP2 	= this.ua.match(/SV1/) != null && this.isWinXP;
		this.isWin2k3 		= this.ua.match(/Windows NT 5.2/) != null;
		this.isMac			= this.ua.match(/Mac/) != null;
		this.isWin2k		= this.ua.match(/Windows (NT 5\.0|NT 5\.01|2000)/) != null;
		this.isAol 			= this.ua.match(/America Online Browser|AOL/) != null;
		this.isVista 		= this.ua.match(/Windows NT 6.0/) != null;
		this.isWin7 		= this.ua.match(/Windows NT 6.1/) != null;
		this.is64bitVista 	= this.isVista && this.is64bitIE;
		
		// properties specific to funnel

		this.xpiinstalled	= window.location.href.indexOf("xpiinstalled") > -1;
		this.isDistrib		= $("eventname") ? $F("eventname") == "readerenterprise" : false;
		this.theBho 		= null;
		this.install_method = "sai";
		this.dlm_compatible_config	= this.is_dlm_compatible_config();
		this.dlm_compatible_installer = 1;
		this.can_bundle_with_air = 0;
	},
	
	// return the value of a text node within an option element
	select_textnode   :   function(element) {
    	return element.options[element.selectedIndex].text;
    },
	
	// tests whether or not getPlus is installed on users machine
	gp_installed   :   function(){
		var found = false;
	
		try {
			for (i = 0; i < navigator.plugins.length && found==false; i++) {
				if (navigator.plugins[i].description.indexOf('getplusplusadobe') > -1) {
					found = true;
				}
			}
		} catch (e) {
			// if accessing plugin properties fails, usually because an item has no property - 
			// seen when plugin just have been installed, without browser restart or page refresh
			found=true;
		}
	
		return found;
	},
	
	is_dlm_compatible_config   :   function() {
		// verifies DLM compatibility based off of the config
		if((this.gp_compat_ie || this.gp_compat_ff) && 
		   (this.isWin7 || this.isVista || this.isWinXP || this.isWin2k3 || this.isWin2k) &&
		  !(this.isAol || this.is64bitIE)){
			// config is compatible with DLM
			if(this.gp_compat_ie) 
				this.set_install_method("activex");
			else 
				this.set_install_method("xpi");
			
			return true;
		} else {
			// config is incompatible with DLM
			this.set_install_method("sai");
			return false;	
		}
	},
	
	set_dlm_compatible_installer   :   function(compatibility) {
		this.dlm_compatible_installer = compatibility == 1 || compatibility == "on" ? 1 : 0;
	},
	
	get_dlm_compatible_installer   :   function() {
		return this.dlm_compatible_installer;
	},
	
	dlm_compatible   :   function() {
		var config = this.dlm_compatible_config;
		var installer = this.get_dlm_compatible_installer();
		return config && installer;
	},
	
	set_install_method   :   function(method) {
		this.install_method = method;
	},
	
	get_install_method   :   function() {
		return this.install_method;
	},
	
	set_can_bundle_with_air   :   function(version, language) {
		if(!this.dlm_compatible()) return;
		
		var major_version = "";
		
		// the main flow calls this method with no arguments, so we must get version/language directly from the page
	 	version = version != undefined ? version : parseInt($("clientversion").innerHTML);
		language = language != undefined ? language : $("language").innerHTML;
		
		// ensure we have a string so we can perform an indexOf	
		version = version.toString();
		
		if(version.indexOf(".") > -1) {
			major_version = version.substring(0, version.indexOf("."));
		} else {
			major_version = version;
		}

		if (major_version.match(/9/) && language.match(/English/) && addons.getInstallAir()) {
			if(acrobatBundle) offers.enable("AcrobatBundle");
			this.can_bundle_with_air = 1;
		}
		else {
			if(acrobatBundle) offers.disable("AcrobatBundle");
			this.can_bundle_with_air = 0;
		}
	},
	
	get_can_bundle_with_air   :   function(){
		return this.can_bundle_with_air;		
	},
	
	// event handler for load of thank you page
	loadHandler_thanks   :   function() {
		if(!this.xpiinstalled && (this.isFirefox && !(this.isMac && this.isDistrib))) {
			this.install();
		}
	},
	
	// trigger firefox's xpi install
	install   :   function() {
		InstallTrigger.install(xpi);
	},
	
	// Taken from http://www.netlobo.com/url_query_string_javascript.html and modified slightly
	gup   :   function(name) {
		name = name.replace(/[\[]/,'\\\[').replace(/[\]]/,'\\\]');
		var regexS = '[\\?&]'+name+'=([^&##]*)';
		var regex = new RegExp(regexS);
		var results = regex.exec(window.location.href);
		return results == null ? false : results[1];
	},
	
	/**
	* Returns the value of the selected radio button in the radio group, null if
	* none are selected, and false if the button group doesn't exist
	*
	* @param {radio Object} or {radio id} el
	* OR
	* @param {form Object} or {form id} el
	* @param {radio group name} radioGroup
	*/
	$RF: function(el, radioGroup) {
	    if($(el).type && $(el).type.toLowerCase() == 'radio') {
	        var radioGroup = $(el).name;
	        var el = $(el).form;
	    } else if ($(el).tagName.toLowerCase() != 'form') {
	        return false;
	    }
	
	    var checked = $(el).getInputs('radio', radioGroup).find(
	        function(re) {return re.checked;}
	    );
	    return (checked) ? $F(checked) : null;
	}
});
// replaces file sizes with , instead of . for locales like french
var dotToComma = function(size) {
		size = size.toString().gsub(/\.+/,',');
		return size;
	}
// replaces file sizes with . instead of , this way we can add stuff up
var commaToDot = function(size) {
	size = size.toString().gsub(/\,+/,'.');
	return size;
}

var otherLocale = function() {
	var loc = (locale == 'fr' || locale == 'de' || locale == 'es'|| locale == 'it' || locale == 'br' || locale == 'se' || locale == 'nl' || locale == 'no' || locale == 'fi' || locale == 'dk') ? true : false;
	return loc;
	
}


var errorHandler = function (e) {
	try {
		var errorName = e.name;
		var errorMessage = e.message;
	
		var jsErrorPing = new adobe.Deeppurple.Event("PDLC","JSError","JSError.gif");
		jsErrorPing.run($H({
			id: "deeppurpleFailure",
			currentURL: document.location,
			errorName: errorName,
			errorMessage: escape(errorMessage)
		}));
		jsErrorPing.send();
	}
	catch (e1) {
		url = "<img src=''http://www.adobe.com/deeppurple/JSError.gif?id=deeppurpleFailure" + "&currentURL=" + document.location + "&errorName=" + e1.name + "&errorMessage=" + escape(e1.message) + "'' />"
		document.getElementById("JSError").innerHTML += url; 
	}
	
}

/**
 * @projectDescription	3rd Party Offers library
 * @namespace adobe.polarbear
 * @author Kevin Favro kfavro@adobe.com
 * @author Chris Lechner clechner@adobe.com
 * 
 * $Header: /source/docroot/downloadcenter/js/offers.js,v 1.14 2009/12/03 22:33:09 rusliu Exp $
 */

// Create the adobe.polarbear namespaces
if (!adobe) abort();
if (!adobe.polarbear) adobe.polarbear = {};
if (!adobe.polarbear.products) adobe.polarbear.products = {};
if (!adobe.polarbear.DLM) adobe.polarbear.DLM = {};

/**
 * adobe.polarbear.offers
 */
adobe.polarbear.offers = Class.create({
	/**
	 * @constructor
	 */
	initialize : function() {
		this.utility = new adobe.polarbear.utility();
		this.container = $H();
		
		// create different category hashes within products
		this.products = $H({
			all : $H(),
			byClass: $H(),
			byType: $H({
				addon : [], 
				core : []
			}),
			byName: $H()
		});
		
		// Map class names to a regular expression
		this.classMap = $H({
			GTB: /^Google Toolbar/i, 
			MSS: /^McAfee/i
		});
	},
	
	/**
	 * Takes a JSON structure of installer meta-data returned from
	 * the polar bear criteria table, instantiates, and prepare()s product 
	 * classes based on matching the installer name property against classMap.
	 * After the product class has been prepare()ed, instances are then stored
	 * as members in the products hash.  
	 * 
	 * @param   json  a json structure containing installer meta-data
	 * @return        void
	 */
	loadProducts : function(json) {
		var j = json;
		var map = this.classMap;
		
		j.each(function(item) {
			map.each(function(regex) {
				if (item.Name.match(regex.value)) {
					try {
						// instantiate a new product class with the same name as the classMap key
						product = new adobe.polarbear.products[regex.key](item, this.utility).prepare();						
						this.categorize(regex.key, product);						
					} catch(e) {}
				}
			}.bind(this));
		}.bind(this));
		
	},
	
	categorize: function(key, product) {
		var qName = product.properties.queryName;
		var byName = qName ? qName : key; 
		
		try {
			// begin storing instances of product classes into hashes organized by category
			this.products.get("all").set(key, product);
			
			if (this.products.get("byClass").get(key)) 
				this.products.get("byClass").get(key).push(product);
			else 
				this.products.get("byClass").set(key, new Array(product));
			
			this.products.get("byType").get(product.type).push(product);
			this.products.get("byName").set(byName, product);
		} catch(e) {}
	},
	
	/**
	 * Sets a product class' eligibility to true
	 * 
	 * @param  id  name of the product class to enable
	 * @return     void
	 */
	enable : function(id) {
		this.products.get("all").get(id).eligible = true;
	},
	
	/**
	 * Set's a product class' eligibility to false
	 * 
	 * @param  id  name of the product class to disable
	 * @return     void
	 */
	disable : function(id) {
		this.products.get("all").get(id).eligible = false;
	},
	
	/**
	 * Loops through Omniture relevant products in the 
	 * products.byClass hash and sets Omniture meta-data
	 * on each product.  The Omniture variable sProp_34
	 * will be set to the value this method returns.
	 * 
	 * @return  a string representing the status of all
	 *          Omniture relevant products
	 */
	toOmnitureString : function() {
		var state = $H();
		
		if (this.products.get("all").size()) {
			this.products.get("all").each(function(item) {
				var usesOmniture = item.value.usesOmniture;
				var preinstalled = item.value.preinstalled;
				var eligible = item.value.eligible;
				
				if(usesOmniture) {
					if(preinstalled) state.set(item.key, "offer-preinstalled");
					else if (eligible) state.set(item.key, "offer-eligible");
					else state.set(item.key, "offer-ineligible");
				}
			});
			
			return state.toQueryString();
		} else {
			return "offer-ineligible";
		}
	},
	
	/**
	 * Loops through all products in the products.byClass hash
	 * and sets each product.queryName equal to a pre-determined
	 * value (p, i, a, d).  The return from this method will be
	 * appended to the thankyou page href.
	 * 
	 * @param  choice  boolean value representing the state of
	 * 				   the addon checkbox
	 * @return 		   a string representing the eligibility and
	 * 				   acceptance status of all products 
	 */
	toQueryString : function(choice) {		
		var state = $H({ p : [], i : [], a : [], d : [] });
		
		this.products.get("all").each(function(item) {
			var usesOmniture = item.value.usesOmniture;
			var preinstalled = item.value.preinstalled;
			var eligible = item.value.eligible;
			var queryName = item.value.properties.queryName;
			
			if(usesOmniture) {
				if(preinstalled) state.get('p').push(queryName);
				else if (eligible && choice == 0) state.get('d').push(queryName);
				else if (eligible && choice == 1) state.get('a').push(queryName);
				else state.get('i').push(queryName);
			} else {
				if(eligible) {
					// Acrobat Bundle will be an array
					if(queryName instanceof Array) {
						for(i=0;i<queryName.length;i++) {
							state.get('a').push(queryName[i]);
						}
					}
					else {
						state.get('a').push(queryName);
					}
				}
			}
		});
		
		// since state values are arrays, we need to remove all empty
		// arrays since toQueryString() returns empty arrays as '&'
		state.each(function(item) {
			if(!item.value.length) state.unset(item.key);
		});	
		
		return state.toQueryString();		
	},
	
	/**
	 * Returns all products of a related class
	 * by searching through products.byClass hash
	 * 
	 * @param  className  name of the class
	 * @return     		  an instance of the requested product class
	 */
	getProductsByClass : function(className) {
		return this.products.get("byClass").get(className);
	},
	
	/**
	 * Returns all products of a related type
	 * by searching through the products.byType hash
	 * 
	 * @param  type  type of class (addon or core)
	 * @return       an instance of the requested product class
	 */
	getProductsByType : function(type) {
		return this.products.get("byType").get(type);		
	},
	
	/**
	 * Returns a product by searching through the 
	 * products.byName hash
	 * 
	 * @param  name  installer query name
	 * @return   	 an instance of the requested product class
	 */
	getProductByName : function(name) {
		return this.products.get("byName").get(name);
	},
	
	/**
	 * Returns a single product by searching through the
	 * products.all hash
	 * 
	 * @param  id  key stored in products.all hash
	 * @return     an instance of the requested product class
	 */
	getProduct : function(id) {		
		return this.getProducts().get(id);
	},
	
	/**
	 * Returns all products stored in the products.all hash
	 * 
	 * @return  all instances of product classes that have been instantiated
	 */
	getProducts : function() {
		return this.products.get("all");
	}
});

/**
 * adobe.polarbear.rdcOffers
 */
adobe.polarbear.rdcOffers = Class.create(adobe.polarbear.offers, {
	initialize: function($super) {
		// initialize the parent class
		$super();
	},
	
	loadProducts: function($super, json) {
		var j = json;
		var temp = "";
		var bundleAcrobat = false;
		var bundleClassName = "AcrobatBundle";
		var bundleDetails = {
			"file_size": 0,
			queryName: []
		};
		
		// load up shared offers using the parent class
		$super(j);
		
		this.bundleClassMap = $H({
			ARH: /^ARH/i, 
			ACROBAT: /^Acrobat\.com/i,
			AIR: /^Air\ Installer/i	
		});
		
		j.each(function(item) {
			this.bundleClassMap.each(function(regex) {
				if (item.Name.match(regex.value)) {
					temp = bundleDetails.file_size;
					bundleDetails.file_size = Math.round((temp + item.file_size)*100)/100;
					temp = bundleDetails.queryName;
					bundleDetails.queryName.push(item.queryName);
					
					throw $break;
				}
			}.bind(this));
		}.bind(this));

		if(bundleDetails.queryName.length == this.bundleClassMap.size()) {
			try {
				// instantiate a new product class with the same name as the classMap key
				product = new adobe.polarbear.products[bundleClassName](bundleDetails, this.utility).prepare();
				// begin storing instances of product classes into hashes organized by category
				this.categorize(bundleClassName, product, true);
			} 
			catch (e) {}
		}
	}	
});

/**
 * A base Class representing a generic offer
 * 
 * adobe.polarbear.products.base
 */
adobe.polarbear.products.base = Class.create({
	/**
	 * @constructor
	 * @return       void
	 */
	
	initialize : function(properties, utility) {
		this.properties = properties;
		this.utility = utility;
		this.type = null;
		this.usesOmniture = false;
		this.preinstalled = false;
		this.eligible = true;

	},
	
	/**
	 * More or less an abstract method.  Child classes will
	 * need to override within themselves.
	 * 
	 * @return  boolean
	 */
	userIsEligible : function() {
		this.eligible = true;
	}
});

/**
 * A Class representing a Google Toolbar offer
 * 
 * @extends adobe.polarbear.products.base
 */
adobe.polarbear.products.GTB = Class.create(adobe.polarbear.products.base, {
	/**
	 * @constructor
	 * @param  $super  	   reference to parent class
	 * @param  properties  object returned from polar bear container
	 * @param  utility     an instance of the utility class
	 * @return 			   self
	 */
	initialize : function($super, properties, utility) {		
		// initialize common properties from the base class
		$super(properties, utility);
		
		// initialize local properties
		this.type = "addon";
		this.usesOmniture = true;
		this.properties = properties;
		return this;
	},
	
	/**
	 * Runs preinstallation and eligibility checks, and stores
	 * results in instance members
	 * 
	 * @return self
	 */
	prepare : function() {
		this.preinstalled = this.isVerGTE();
		this.eligible = this.preinstalled ? false : this.userIsEligible();
		return this;	
	},
	
	/**
	 * GTB eligibility test
	 * 
	 * @return  boolean
	 */
	userIsEligible : function() {
		var u = this.utility;
		return (((u.isWin2k3 || u.isWinXP || u.isWinVista || u.isWin7) && (u.isIE6 || u.isIE7 || u.isIE8)) && !u.isAol);
	},
	
	/**
	 * Runs GTB preinstallation test
	 * 
	 * @return  boolean
	 */
	isVerGTE: function() {
		try {
			var theBho = this.initBho();
			if (null != theBho) {
				return true;
			} else {
				return false;
			}
		} catch (err) { return true; }
	},

	/**
	 * GTB preinstallation test 
	 * 
	 * @return  string
	 */
	initBho: function() {
		var bInitBho = false;
		var theBho = null;
		if(!bInitBho) {
			bInitBho = true;
	
			var y = document.createElement( "div" );
			var bho = document.createElement( "OBJECT" );
			bho.width = 1;
			bho.height = 1;
			bho.classid ="clsid:2318C2B1-4965-11d4-9B18-009027A5CD4F";
			bho.id ="bho";
			y.appendChild( bho );
	
			var bho2 = document.createElement( "OBJECT" );
			bho2.width = 1;
			bho2.height = 1;
			bho2.classid ="clsid:2318C2B1-4965-11d4-9B18-009027A5CD4F";
			bho2.id ="bho2";
			y.appendChild( bho2 );
	
			if (null != bho2 && "undefined" != typeof(bho2) && null != bho2.object) {
				theBho = bho2;
			} else if (null != bho && "undefined" != typeof(bho) && null != bho.object) {
				theBho = bho;
			}
		}
	
		return theBho;
	}
	
});

/**
 * A Class representing a McAfee Security Scan offer
 * 
 * @extends adobe.polarbear.products.base
 */
adobe.polarbear.products.MSS = Class.create(adobe.polarbear.products.base, {
	/**
	 * @constructor
	 * @param  $super  	   reference to parent class
	 * @param  properties  object returned from polar bear container
	 * @param  utility     an instance of the utility class
	 * @return 			   self
	 */
	initialize : function($super, properties, utility) {		
		// initialize common properties from the base class
		$super(properties, utility);
		
		// initialize local properties
		this.type = "addon";
		this.usesOmniture = true;
		this.properties = properties;

		return this;
	},
	
	/**
	 * Runs eligibility check and stores
	 * results in instance member
	 * 
	 * @return self
	 */
	prepare : function() {
		this.eligible = this.userIsEligible();
		return this;
	},
	
	/**
	 * MSS eligibility test
	 * 
	 * @return  boolean
	 */
	userIsEligible : function() {
		var u = this.utility;
		return ((u.isWinXP || u.isWinVista || u.isWin7) && ((u.isIE6 || u.isIE7 || u.isIE8) || (u.isFF2 || u.isFF3)) && !u.isAol);
	}
});

/**
 * A Class representing a Acrobat.com offer
 * 
 * @extends adobe.polarbear.products.base
 */
adobe.polarbear.products.AcrobatBundle = Class.create(adobe.polarbear.products.base, {
	/**
	 * @constructor
	 * @param  $super  	   reference to parent class
	 * @param  properties  object returned from polar bear container
	 * @param  utility     an instance of the utility class
	 * @return 			   self
	 */
	initialize : function($super, properties, utility) {		
		// initialize common properties from the base class
		$super(properties, utility);
		
		// initialize local properties
		this.type = "addon";
		this.usesOmniture = false;
		this.properties = properties;

		return this;
	},
	
	/**
	 * Runs eligibility check and stores
	 * results in instance member
	 * 
	 * @return self
	 */
	prepare : function() {
		this.eligible = this.userIsEligible();
		return this;
	},
	
	/**
	 * Acrobat Bundle eligibility test
	 * 
	 * @return  boolean
	 */
	userIsEligible : function() {
		var u = this.utility;
		return (((u.isWin2k || u.isWin2k3 || u.isWinXP || u.isWinVista || u.isWin7) && (u.gp_compat_ie || u.gp_compat_ff)) && !u.isAol);
	}
});

/**
 * adobe.polarbear.utility
 */
adobe.polarbear.utility = Class.create({
	
	/**
	 * @constructor
	 * @return       void
	 */
	initialize: function(){
		this.ua = navigator.userAgent;
		
		// properties for specific browsers
		this.isIE6 = this.ua.match(/MSIE 6/) != null;
		this.isIE7 = this.ua.match(/MSIE 7/) != null;
		this.isIE8 = this.ua.match(/MSIE 8/) != null;
		this.is64bitIE = this.ua.match(/Win64|x64/) != null;
		this.is32IEonVista64 = this.ua.match(/WOW64/) != null && this.isIE7;
		this.isFF = this.ua.match(/Firefox/) != null;
		this.isFF3 = this.ua.match(/Firefox\/3/) != null;
		this.isFF2 = this.ua.match(/Firefox\/2/) != null;
		this.isFF15 = this.ua.match(/Firefox\/1\.5/) != null;
		this.gp_compat_ie = this.isIE6 || this.isIE7 || this.isIE8;
		this.gp_compat_ff = this.isFF3 || this.isFF2 || this.isFF15;
		
		// properties for specific os/platforms
		this.isWin2k = this.ua.match(/Win(dows)? ?(NT 5.0)/) != null && this.ua.match(/Win(dows)? ?(NT 5.01)/) == null;
		this.isWin2k3 = this.ua.match(/Windows NT 5.2/) != null;
		this.isWinXP = this.ua.match(/Win(dows)? ?(NT 5.1)/) != null;
		this.isWinXPSP2 = this.ua.match(/SV1/) != null && this.isWinXP;
		this.isWinVista = this.ua.match(/Win(dows)? ?(NT 6.0)/) != null;
		this.is64bitVista = this.isWinVista && this.is64bitIE;
		this.isWin7 = this.ua.match(/Win(dows)? ?(NT 6.1)/) != null;
		this.isAol = this.ua.match(/America Online Browser|AOL/) != null;
		this.isMac = this.ua.match(/Mac/) != null;
	}
});

var FPDC = Class.create({	
	bootstrap: function(fetchFP){
		// first create a utlity object for other classes to take advantage of
		utility = new SwissArmyKnife();
		
		offers = new adobe.polarbear.offers();
		
		if(fetchFP) new FP_Request();
		
		// load FP_Display Class
		new FP_Display();
		
		// create a addons object for other classes to take advantage of
		if (window.addonsjson) {
			addons = new Addons();
			addons.processAddons();
		}
		
		if(!fetchFP) document.fire("display:main");
	}
});


/* ***************************************
 * FP_ CLASSES OVERWRITTING BASE CLASSES
 *************************************** */

var FP_Request = Class.create(Request, {
	
	initialize	:	function() {
		this.fakeAgent = {                     
		 	Windows   : { platform_type: "Windows", platform_dist: "XP", platform_arch: "x86-32", platform_misc: "", browser_type: "", browser_dist: "", browser_vers: "" },
	        Windows98 : { platform_type: "Windows", platform_dist: "98", platform_arch: "x86-32", platform_misc: "", browser_type: "", browser_dist: "", browser_vers: "" },
	        Macintosh_10_5 : { platform_type: "Macintosh", platform_dist: "OSX", platform_arch: "x86-32", platform_misc: "10.5.0", browser_type: "", browser_dist: "", browser_vers: "" },
	        Macintosh_10_3 : { platform_type: "Macintosh", platform_dist: "OSX", platform_arch: "PPC", platform_misc: "10.3.0", browser_type: "", browser_dist: "", browser_vers: "" },
	        Linux     : { platform_type: "Linux", platform_dist: "", platform_arch: "x86-32", platform_misc: "", browser_type: "", browser_dist: "", browser_vers: "" },
	        Solaris   : { platform_type: "Solaris", platform_dist: "", platform_arch: "", platform_misc: "", browser_type: "", browser_dist: "", browser_vers: "" }
		};
		
		// event handler for continue button
		$("buttonContinue").observe("click", this._onContinueClick.bindAsEventListener(this));
	},
	
	_onContinueClick   :   function($super,e) {
		try {
			var url = this.getAjaxUrl();
			$super(e);
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	getAjaxUrl	:	function(){
		var url = "/flashplayer/webservices/json/" + this.prepareQueryString();
		return url;
	},
	
	getNoResultDisplay	:	function(){
		return "display:noflashplayer";
	},
	
	getResultDisplay	:	function(eventname){
		var displayResult;
		
		if (eventname == "flashplayerotherversions")
			displayResult = "display:otherversions";

		return displayResult;
	}
});

var FP_Display = Class.create(Display, {
	//installer : null,
	
	initialize   :   function($super) {
		
		// base.js is setting the observe on 'otherversions' and 'noSelection'
		// it is also setting the observer on the buttonDownload
		$super();
		document.observe("display:main", this._displayMain.bindAsEventListener(this));
		document.observe("Flash:addonClick", this._termOfService.bindAsEventListener(this));
	},
	
	_termOfService   :   function() {
		try {
			var theAddon = $('addon').value;
			
			if (theAddon == '' || theAddon == null) 
				$('addon').checked = false;
			
			var checked = $('addon').checked;
			
			if (checked && $("addonoffers").visible()) {
				$('adobeEULA').hide();
				if (theAddon.match(/Google/)) {
					$('googleEULA').show();
				} else {
					$('mcafeeEULA').show();
				}
			}
			else {
				$('adobeEULA').show();
				$('googleEULA').hide();
				$('mcafeeEULA').hide();
			}
		}
			catch (e) {
				errorHandler (e);
		  }
	},	
	_displayMain   :   function(event) {
		try {
			this.makeaddonoffer();	
			this._termOfService();
	        this.updateTotalSize();	
		}
			catch (e) {
				errorHandler (e);
		  }
	},
		
	_displayOtherVersions   :   function(event) {
		try {
			this.buildOffersTable(event.memo);
			for (var i=0; i<event.memo.length; i++) {
				 if (event.memo[i].queryName.match(/APT_for_Ubuntu/)) apt_download_url = event.memo[i].download_url;
				 
			}			
			$("error-message").hide();
			this.adjustAddonDisplay();
			this.curtainsUp();
			}
			catch (e) {
				errorHandler (e);
		  }
	},

	_displayNoFlashPlayer   :   function() {
		
		$("ajaxloading").hide();
	},
	
	_displayNoSelection   :   function() {
		try {
			$("ajaxloading").hide();
			$("error-message").show();
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_displayAddons : function(event) {
		try {
			var fileSize = event.memo.size;
			var div = event.memo.div;
			fileSize = (otherLocale()) ? dotToComma(fileSize) : fileSize;
			$("addonfilesize").update(fileSize);
			$(div).show();
			$("addonlabel").innerHTML = $(div).down("p").innerHTML;
			showaddon = true;
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_onDownloadClick   :   function($super, event) {
		try {
			var basetriggerpage = window.basetriggerpage;
			//var f = document.forms["downloadForm"];
			var radiovalue = $RF('downloadForm', 'installer');
			//if the radio value is null, it is the flash main page flow. set the installer value accordingly
			if (radiovalue == null)	radiovalue = $("installer").value;
	
			if (utility.dlm_compatible()){
				switch (utility.get_install_method()) {
					case "activex":
						if (radiovalue.match(/Internet_Explorer/))
							basetriggerpage += "activex/";
						basetriggerpage += "?installer=" + radiovalue;
						basetriggerpage += '&' + offers.toQueryString($("addon").checked);
						break;
						
					case "xpi":	
						if (radiovalue != null) {
							
							if (!radiovalue.match(/Internet_Explorer/))
								basetriggerpage += "xpi/";
						}
						basetriggerpage += "?installer=" + radiovalue;
						basetriggerpage += '&' + offers.toQueryString($("addon").checked);
						break;					
	
					case "sai":
						basetriggerpage += "?installer=" + radiovalue;
					default:
						basetriggerpage += "?installer=" + radiovalue;
	
				};
			}
			else 
				basetriggerpage += "?installer=" + radiovalue;
				
			 if (radiovalue.match(/APT_for_Ubuntu/)) basetriggerpage = apt_download_url; //this is for bug fix 103004
			 
			$('buttonDownload').setAttribute('href',basetriggerpage);
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	
	getTemplate	:	function() {
		var template = new Template('\n\t<tr>\n' +
                                        '\t\t<td width="20"><input id="offer#{id}" value="#{queryName}" name="installer" type="radio"></td>\n' +
                                        '\t\t<td width="208"><label class="top" for="offer#{id}">#{name}</label></td>\n' +
                                    '\t</tr>\n');
		return template;
	},
	
	getTemplateProperties	:	function(offer) {
		var template_properties = {id : offer.id, version : offer.Version, name: offer.Name, browser: offer.browser, queryName: offer.queryName};
		return template_properties;
	},
	
	highlightandupdate   :   function($super, button, item) {
    	$("browserinfo").update(item.browser);
        $super(button, item);
		//for linux YUM show KB else MB bug 101847
		if(button.value.endsWith('(YUM)'))
		{
			$("mbsize").hide();
			$("kbsize").show();
		}
		else
		{
			$("mbsize").show();
			$("kbsize").hide();
		}
    },
	
	adjustofferbox   :   function($super, canusedlm, button, item) {
		
        // update reader size/requirements url and highlight selected row
        $super(canusedlm, button, item);
		
        // update total size field based on state of addon offer checkbox
        this.updateTotalSize();
		this.adjustAddonDisplay();
    },
	
	buildItem		:	function($super,offer) {
		var item = $super(offer);
		
		item.browser = offer.browser;
		/*
		if (offer.queryName == "Flash_Player_10_for_Windows_Internet_Explorer")
			this.installer = offer.queryName;
		*/
		return item;
	},
	
	adjustAddonDisplay	:	function() {
		var radiovalue = $RF('downloadForm', 'installer');
		if (utility.dlm_compatible()){
			switch (utility.get_install_method()) {
			case "activex":
				if (!radiovalue.match(/Internet_Explorer/)) {
					$("addonoffers").hide();
				}
				else {
					if ((GTBOBJ && GTBOBJ.eligible) || (MSSOBJ && MSSOBJ.eligible)) {
						$("addonoffers").show();
					}
				}
				break;
						
			case "xpi":	
				if (GTBOBJ) offers.disable("GTB");
				if (!radiovalue.match(/Windows_-_Other/)) {
					if (MSSOBJ) offers.disable("MSS"); //disable mss to get proper query strings
					$("addonoffers").hide();
				}
				else {
					 offers.enable("MSS");
					$("addonoffers").show();
				}
				break;
			case "sai":
			default:
				};			
		}
		else 
		$("addonoffers").hide();
	this._termOfService();
	}	
	
});

var Addons = Class.create({
		
		initialize   :   function() {
			if(window.addonsjson == undefined) return;

			this.addons = addonsjson;
			
			//this.installAir = 0;
			//this.airInstallSize = 0;
			return this;
		},
		
		processAddons   :   function() {

			//var i 		= "";
			//var gtbinstalled = false;
			s_prop34 = "FP: ";
			
			offers.loadProducts(addonsjson);
			
			GTBOBJ = offers.getProduct("GTB");
			
			MSSOBJ = offers.getProduct("MSS");
			
			if (utility.dlm_compatible()) {
				// check to see if gtb is available, else display mss offer
				
				if (GTBOBJ && GTBOBJ.eligible) {
						
							if (MSSOBJ) offers.disable("MSS");
						if (utility.get_install_method() == 'activex') {
							$("addon").value = GTBOBJ.properties.queryName;
							document.fire("display:addons", {
								size: GTBOBJ.properties.file_size,
								div: "GTB"
							});
						}
						else
							offers.disable("GTB");
				}
				else {
						if (MSSOBJ && MSSOBJ.eligible) {
							if (utility.get_install_method() == 'xpi' || utility.get_install_method() == 'activex') {
								$("addon").value = MSSOBJ.properties.queryName;
								document.fire("display:addons", {
								size: MSSOBJ.properties.file_size,
								div: "MSS"
								});
							}
							else 
								if (MSSOBJ) {
									offers.disable("MSS");
								}
						}
				}
					
			}
			s_prop34 += offers.toOmnitureString();
			
		},
		
		showaddondiv : function (divname,addonname,addonnamedisplay) {
			$(divname).show();
			$("addonlabel").innerHTML = $(addonnamedisplay).innerHTML;
			$("addon").value = addonname;
        	$("addon").checked = true;
			
		}
});


/**
* Returns the value of the selected radio button in the radio group, null if
* none are selected, and false if the button group doesn't exist
*
* @param {radio Object} or {radio id} el
* OR
* @param {form Object} or {form id} el
* @param {radio group name} radioGroup
*/
function $RF(el, radioGroup) {
    if($(el).type && $(el).type.toLowerCase() == 'radio') {
        var radioGroup = $(el).name;
        var el = $(el).form;
    } else if ($(el).tagName.toLowerCase() != 'form') {
        return false;
    }

    var checked = $(el).getInputs('radio', radioGroup).find(
        function(re) {return re.checked;}
    );
    return (checked) ? $F(checked) : null;
}
