/*
	file:	        reader.js
	description:	extends classes from base.js
	$Header: /source/docroot/downloadcenter/js/reader.js,v 1.21 2009/12/17 10:18:03 krao 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 RDC = Class.create({

	bootstrap   :   function(fetchReader) {
		// first create a utlity object for other classes to take advantage of
		utility = new SwissArmyKnife();
		
		offers = new adobe.polarbear.rdcOffers();
		
		// not all funnels need an ajax request for reader items
		if(fetchReader) new RDR_Request();
				
		// load Display Class
        new RDR_Display();

		// create a addons object for other classes to take advantage of
        if (window.addonsjson) {
			addons = new Addons();
			addons.processAddons();
		}
		
		if(!fetchReader) document.fire("display:main");
	}	
});

/* ***************************************
 * RDR_ CLASSES OVERWRITTING BASE CLASSES
 *************************************** */

var RDR_Request = Class.create(Request, {

	initialize   :   function() {
		this.fakeAgent = {
			Win7: { platform_type : "Windows", platform_dist : "Windows 7", platform_arch : "x86-32" },                     
			WinVista : { platform_type : "Windows", platform_dist : "Vista", platform_arch : "x86-32" },
			WinXPSP3 : { platform_type : "Windows", platform_dist : "XP", platform_arch : "x86-32", platform_misc : "SP3" },
			WinXPSP2 : { platform_type : "Windows", platform_dist : "XP", platform_arch	: "x86-32", platform_misc	: "SP2" },                           
			Win2008	: { platform_type : "Windows", platform_dist : "2008", platform_arch : "x86-32" },                       
			Win2003	: { platform_type : "Windows", platform_dist : "2003", platform_arch : "x86-32" },    
			Win2000SP4 : { platform_type : "Windows", platform_dist : "2000", platform_arch : "x86-32", platform_misc : "SP4" },
			Win2000 : { platform_type : "Windows", platform_dist : "2000", platform_arch : "x86-32", platform_misc : "SP3" },
			WinNT6 : { platform_type : "Windows", platform_dist : "NT", platform_arch	: "x86-32", platform_misc	: "SP6" },
			MacIntel_1060 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "x86-32", platform_misc : "10.6.0" },
			MacIntel_1055 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "x86-32", platform_misc : "10.5.5" },
			MacPPC_1060 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "PPC", platform_misc	: "10.6.0" },
			MacPPC_1055 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "PPC", platform_misc	: "10.5.5" },
			MacIntel_10410 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "x86-32", platform_misc : "10.4.10" },
			MacPPC_10410 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "PPC", platform_misc	: "10.4.10" },
			MacPPC_1042 : { platform_type : "Macintosh", platform_dist : "OSX", platform_arch : "PPC", platform_misc	: "10.4.2" },
			Linux_bin : { platform_type : "Linux", platform_arch : "x86-32", installer_extension : ".bin" },
			Linux_tar_gz : { platform_type : "Linux", platform_arch : "x86-32", installer_extension : ".tar.gz" },
			Linux_rpm : { platform_type : "Linux", platform_arch : "x86-32", installer_extension : ".rpm" },
			Linux_tar_bz2 : { platform_type : "Linux", platform_arch : "x86-32", installer_extension : ".tar.bz2" },
			Linux_deb : { platform_type : "Linux", platform_arch : "x86-32", installer_extension : ".deb" },
			Solaris_bin	: { platform_type : "Solaris", platform_arch : "x86-32", installer_extension : ".bin" },
			Solaris_tar_bz2	: { platform_type : "Solaris", platform_arch : "x86-32", installer_extension : ".tar.bz2" },
			Solaris_pkg_bz2	: { platform_type : "Solaris", platform_arch : "x86-32", installer_extension : ".pkg.bz2" },
			Solaris_SPARC_tar_gz : { platform_type : "Solaris", platform_arch : "SPARC", installer_extension : ".tar.gz" },
			Solaris_SPARC_tar_bz2 : { platform_type : "Solaris", platform_arch : "SPARC", installer_extension : ".tar.bz2" },
			IBM_AIX : { platform_type : "AIX", platform_arch : "x86-32" },
			HP_UX : { platform_type : "HP-UX", platform_arch : "x86-32" }
		};

		
		// event handler for continue button
		$("buttonContinue").observe("click", this._onContinueClick.bindAsEventListener(this)); 
		
		var eventname = $F("eventname");
		
		// Bug 96560 - if user chooses Mobile, reduce language list to just English
		$("select_os").observe("change", this._onOsSelection.bindAsEventListener(this,eventname));
	},
	
	_onContinueClick   :   function($super,e) {		
		// Bug 96560 - redirect users who are downloading mobile version
		if($F("select_os") == "Mobile")  return location.href = "http://www.quickoffice.com/store/s60-3rd-edition/adobe-reader-le-v25/";
		var url = this.getAjaxUrl();
		$super(e);
	},
	
	getAjaxUrl	:	function(){
		var url = "/reader/webservices/json/standalone/" + this.prepareQueryString();
		return url;
	},
	
	getNoResultDisplay	:	function(){
		return "display:noreader";
	},
	
	getResultDisplay	:	function(eventname){
		var displayResult;

		switch(eventname) {		
			case "readermoreinfo" :
				displayResult = "display:moreinfo";
				break;
			
			case "readerotherversions" :
				displayResult = "display:otherversions";
				break;
			
			case "readerenterprise" :
				displayResult = "display:enterprise";
				break;
		}

		return displayResult;
	},
	
	_onOsSelection     :   function(e,eventname) {
		if (eventname == "readerotherversions")
		{
			if($F("select_os") == "Mobile") {
				$("select_language").hide();
				$("language_label").hide();
				$("mobileLanguage").show();
			} else {
				$("select_language").show();
				$("language_label").show();
				$("mobileLanguage").hide();
			}
		}
		
	},
	
	// use parent class to create query string, then append language value
	prepareQueryString	   :   function($super) {
		var query_string = $super();
		var language = $F("select_language");
		
		query_string += "&language=" + language;

		return query_string;
	}
});

var RDR_Display = Class.create(Display, {
	
	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("display:moreinfo", this._displayMoreInfo.bindAsEventListener(this));
		
		document.observe("display:enterprise", this._displayEnterprise.bindAsEventListener(this));
		
		document.observe("display:noreader", this._displayNoReader.bindAsEventListener(this));
		
		// if user is on step2 and changes their language preference, reset page (OS reset is happening in the base.js)		
		if($("select_language")) $("select_language").observe("change", this.curtainsDown);
		
		acrobat_bundle_string = /<br(\s\/)?>\(includes Acrobat\.com on Adobe AIR\)/i;
	},
	
	_displayMain   :   function(event) {
		// we need to process the version in case we have a Reader 9 that isn't
		// actually compatible with the air bundle (ex: Win7)
		try {
			if($('installer').value.match(/(Win|Windows)/)) $("clientversion").update(this.processVersion($("clientversion").innerHTML));
			utility.set_can_bundle_with_air();
			this.makeaddonoffer();		
			this.updateClientSize();		
			this.updateTotalSize();
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_displayMoreInfo   :   function(event) {
		try {
			var item = event.memo[0];
			var dlm_compatible_installer = item.can_use_dlm;
			utility.set_dlm_compatible_installer(dlm_compatible_installer);
			utility.set_can_bundle_with_air(item.Version, item.language_type);
			
			$("installer").value = item.queryName;
			$("platformlabel").update(utility.select_textnode($("select_os")));
			if(otherLocale()) {
				item.file_size = dotToComma(item.file_size);
			}
			$("clientfilesize").update(item.file_size);
			$("clientversion").update(item.Version);
			//remove "acrobat.com on Adobe AIR" text from win2k.bug#106373
			if($('installer').value.match(/(Win|Windows)/))$("clientversion").update(this.processVersion(item.Version));
			$("system_requirements").writeAttribute("href", locPathToAdobe + item.systemreqs_url + "#" + item.systemreqs_anchor);
			this.makeaddonoffer();
			
			// update client size and if air/apps will be bundled
			if(utility.get_can_bundle_with_air()) {
				this.updateClientSize();
			}
				
			this.updateTotalSize();
			this.curtainsUp();
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_displayOtherVersions   :   function(event) {
		try {
			this.buildOffersTable(event.memo);
			$("selectedPlatform").update(utility.select_textnode($("select_os")));
			$("selectedLanguage").update(utility.select_textnode($("select_language")));
			$("error-message").hide();
			this.curtainsUp();
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_displayEnterprise   :   function(event) {
		try {
			var item = event.memo[0];
			$("installer").value = item.queryName;
			if(otherLocale()) {
				item.file_size = dotToComma(item.file_size);
			}
			$("clientfilesize").update(item.file_size);
			$("clientversion").update(item.Version);
			this.curtainsUp();
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_displayNoReader   :   function() {
		try {
			$("ajaxloading").hide();
			$("unavailable").toggle();	
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_onDownloadClick   :   function(event) {
		try {
			var f = document.forms["downloadForm"];
			var eventname = $("eventname").value;
			var radioChoice = utility.$RF('downloadForm', 'installer');
			var installer = "?installer=";
			installer += radioChoice != null ? radioChoice : $F("installer");
			var choice = $("addon") ? $("addon").checked : false;
			var addons = offers.toQueryString(choice);
			var queryString = installer + "&" + addons;
			var href = $('buttonDownload');
			
			if (eventname != "readerenterprise" && utility.dlm_compatible()) {
				// set our action based on the install method
				switch (utility.get_install_method()) {
					case "activex":
						href += "activex/" + queryString;
						break;
					case "xpi":
						href += "xpi/" + queryString;
						break;
					case "sai":
					default:
						href += queryString;
				};
			} else {
				href += installer;
			}
	
			$('buttonDownload').setAttribute("href", href);	
		}
			catch (e) {
				errorHandler (e);
		  }
	},
	
	_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);
		  }
	},
	
	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="155"><label class="top" for="offer#{id}">Adobe Reader #{version}</label></td>\n' +
                                    '\t</tr>\n');
		return template;
	},
	
	getTemplateProperties	:	function(offer) {
		// if this is a Windows installer we're dealing with, run through the processVersion method
		// so we can determine if we need to strip any air bundle info from the version number.  If
		// this is a Mac installer (or anything else) we don't need to process the version, since 
		// English Mac installers have Air/Acrobat bundled in to the installer.
		
		var installerVersion;
		if (offer.queryName.match(/Windows/)) installerVersion = this.processVersion(offer.Version);
		else installerVersion = offer.Version;	
		var template_properties = {id : offer.id, version : installerVersion, queryName : offer.queryName};
		return template_properties;
	},
	
	curtainsDown   :   function($super) {
		$super();
		if($("unavailable") && $("unavailable").getStyle("display") != "none") $("unavailable").hide();
	},
        
    highlightandupdate   :   function($super, button, item) {
		$super(button, item);
        $("system_requirements").writeAttribute("href", locPathToAdobe + item.url + "#" + item.anchorname);
    },
	
	adjustofferbox   :   function($super, button, item) {
        
        // update reader size/requirements url and highlight selected row
        $super(button, item);
		
		// determine if we can bundle with air
		utility.set_can_bundle_with_air(item.version, item.language)
		
		if(utility.get_dlm_compatible_installer() && utility.get_can_bundle_with_air()) {
			this.updateClientSize();
		}
		
        // update total size field based on state of addon offer checkbox
        this.updateTotalSize();
    },
	
	buildItem		:	function($super,offer) {
		var item = $super(offer);
		item.anchorname = offer.systemreqs_anchor;
		item.version	= offer.Version;
		item.language	= offer.language_type;
		
		return item;
	},

	updateClientSize   :   function() {
		if(acrobatBundle && acrobatBundle.eligible) {
			client = parseFloat($("clientfilesize").innerHTML);
			bundle = acrobatBundle.properties.file_size;
			$("clientfilesize").update(Math.round((client + bundle)*100)/100);
		}
	},
	
	processVersion   :   function(version) {
		// installers that can be bundled with air/acrobat have an extra descriptive string
		// in the version field from the admin.  the possibity exists that a user could request
		// an installer that is able to be bundled with air/acrobat, but their configuration
		// is dlm incompatible, so we must remove the air/acrobat information from the version #
		// this will most likely only happen on the otherversions flow
		
		// some version numbers will be considered strings (8.1.3, 9.1 with Acrobat.com....) and
		// some will be numbers.  make sure version is a string so we can perform indexOf() below.
		if(typeof version != "string") version = version.toString();
		
		var found = version.search(acrobat_bundle_string);
		
		if(found != -1 && !addons.getInstallAir()) {
			return version.substring(0, found);
		} else {
			return version;
		}
	}
});

var Addons = Class.create({
		
	initialize   :   function() {
		this.addonsjson = addonsjson;
		this.installAir = 0;
		this.airInstallSize = 0;
		return this;
	},
	
	processAddons   :   function() {
		var i = "";
		s_prop34 = "Reader: ";
		
		offers.loadProducts(addonsjson);			
		gtbobj = offers.getProduct("GTB");			
		mssobj = offers.getProduct("MSS");
		acrobatBundle = offers.getProduct("AcrobatBundle");
		
		if (utility.dlm_compatible()) {
			
			if(gtbobj && gtbobj.eligible) {				
				if(mssobj) offers.disable("MSS");
				
				document.fire("display:addons", {
					size: gtbobj.properties.file_size,
					div: "gtb"
				});				
			} else if(mssobj && mssobj.eligible) {
				document.fire("display:addons", {
					size: mssobj.properties.file_size,
					div: "mss"
				});
			}
			
			if((acrobatBundle && acrobatBundle.eligible)) {
				this.setInstallAir(1);
				this.setAirInstallSize(acrobatBundle.properties.file_size);
			}
		
		}
		
		s_prop34 += offers.toOmnitureString();
	},
	
	setInstallAir   :   function(install) {
		this.installAir = install;
	},
	
	getInstallAir   :   function() {
		return this.installAir;
	},
	
	setAirInstallSize   :   function(size) {
		this.airInstallSize += size;
	},
	
	getAirInstallSize   :   function() {
		return this.airInstallSize;
	}
});