/*******************************************************************************
 * Licensed Materials - Property of IBM
 * Mobile Browser Simulator
 * © Copyright IBM Corporation 2011, 2012. All Rights Reserved.
 *
 * U.S. Government Users Restricted Rights - Use, duplication or 
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *******************************************************************************/

/**
 * Widget used to communicate with a browser plugin to switch the useragent ID.
 * 
 * Current Supports
 * * Firefox
 */
define("ibm_mobile/UseragentSwitcherCommunicator",[
	"dojo",
	"dijit",
	"dijit/_Widget",
	"dijit/_TemplatedMixin",
	"dojo/text!ibm_mobile/templates/UseragentSwitcherCommunicator.html",
	"dojo/i18n"
], function(dojo, dijit, _Widget, _TemplatedMixin, useragentSwitcherCommunicatorTemplate) {

	var UseragentSwitcherCommunicator = dojo.declare("ibm_mobile.UseragentSwitcherCommunicator", [dijit._Widget, dijit._TemplatedMixin ], {
	
		/** Used to debug this widget */
		__DEBUG_ENABLED : false,
		
		// PRIVATE CONST
		/** expected version of the Firefox extension */
		EXTENSION_FF_VERSION : '1.3',
		
		/** expected version of the Chrome extension */
		EXTENSION_CHROME_VERSION : '1.6',
		
		// PUBLIC EVENTS
		onInstall : function() {},
	
		// WIDGET PARAMS
		templateString : useragentSwitcherCommunicatorTemplate,
		
		// PRIVATE
		_deferredSwitchs : null,
		_deferredSwitchsLoopRunning : false,
		
		// DOJO ATTATCH POINTS
		_communicator : null,
	
		/**
		 * <p>Widget lifecycle function.</p>
		 * 
		 * @param params
		 */
		constructor : function(params) {
			this._deferredSwitchs = [];
		},
	
		/**
		 * <p>Widget lifecycle function.</p>
		 */
		postMixInProperties : function() {
		},
	
		/**
		 * <p>Widget lifecycle function.</p>
		 */
		postCreate : function() {
			//check if extension is already installed
			if(dojo.attr(this._communicator, 'data-installed') == 'true') {
				this._install();
			}
			
			// listen for UserAgentSwitch install event
			this._addEventListener('onInstall', dojo.hitch(this, this._install));
			
			//listen for useragent change requests
			dojo.subscribe("/mbs/useragent", dojo.hitch(this, this._switchUseragentID));
		},
		
		isSwitchingInstalled : function() {
			var ret = false;
			if (dojo.attr(this._communicator, 'data-installed') == "true")
				ret = true;
			return ret;
		},
		
		isSwitchingEnabled : function() {
			var ret = false;
			if (dojo.attr(this._communicator, 'data-enabled') == "true")
				ret = true;
			return ret;
		},
		
		setInstalled : function() {
			this.updateCheckbox();			
			dojo.attr(this._communicator, 'data-installed', 'true');
									
			this._addEventListener('onEnablementUpdate', dojo.hitch(this, function(){
					this.updateCheckbox();
				}));
		},
		
		/**
		 * @returns Boolean true if the current browser is supported, false otherwise
		 */
		isBrowserSupported : function() {
			// note that on Firefox, the browser userAgent can possibly be changed by the extension
			// then has("ff") could return undefined...
			// if window.navigator.originalUserAgent is defined, we can deduce that the FF extension is running.
			// and if the FF extension is running then we know that we are using Firefox...
			return dojo.isFF || (typeof window.navigator.originalUserAgent !== 'undefined') 
				|| dojo.isChrome;
		},
		
		/**
		 * @returns {Array} array of Strings of the supported browser names
		 */
		getSupportedBrowserStrings : function() {
			var nls = dojo.i18n.getLocalization("ibm_mobile", "mobile");
			return [nls.Mozilla_Firefox, nls.Google_Chrome];
		},
		
		/**
		 * @returns {String} the local URL path to the extension for the current supported browser,
		 * or NULL if the current browser is not supported
		 */
		getExtensionURL : function() {
			var url = null;
			if(dojo.isFF) {
				url = dojo.moduleUrl("ibm_mobile", "extensions/mbsuseragent@rational.ibm.com.xpi");
			}
			if(dojo.isChrome) {
				url = dojo.moduleUrl("ibm_mobile", "extensions/mbsuseragent@rational.ibm.com.crx");
			}
			return url;
		},
		
		setSwitchingEnabled : function(enabled) {
			dojo.attr(this._communicator, 'data-enabled', "" + enabled);
			this._dispatchEvent('onEnablementChange');
		},
				
		updateCheckbox : function() {
			var switchingEnabled = dojo.attr(this._communicator, 'data-enabled');
			var useragentSwitchingBtn = dijit.byId('_useragentSwitchingEnablementBtn');
			useragentSwitchingBtn.set('checked', (switchingEnabled == 'true')? true : false);
		},
		
		/**
		 * <p>Deal with install of extension.</p>
		 */
		_install : function() {
			if(this._checkExtensionVersion()) {
				//this.setSwitchingEnabled(true);
				
				//notify
				this.onInstall();
			}
		},
		
		/**
		 * @returns {Boolean} true if the installed extension version is as expected, false otherwise
		 */
		_checkExtensionVersion : function() {
			return  (
				((dojo.isFF|| (typeof window.navigator.originalUserAgent !== 'undefined')) 
						&& dojo.attr(this._communicator, 'data-version') == this.EXTENSION_FF_VERSION)
				//version checks for other browsers can go here
				|| (dojo.isChrome && dojo.attr(this._communicator, 'data-version') == this.EXTENSION_CHROME_VERSION)
			);
		},
		
		_switchUseragentID : function(data) {
			this.__log("_switchUseragentID", arguments);
			
			var internalswitchUseragentID = function() {
				this.__log("internalswitchUseragentID", arguments);
				
				var deferred = new dojo.Deferred();
				
				/* if switching installed & enabled then switch useragent before running action
				 * else just run the action
				 */
				if((this.isSwitchingInstalled() == true) 
					&& (this.isSwitchingEnabled() == true)) {
					this.__log("internalswitchUseragentID: switching installed & enabled");
					
					//listen for response
					var listener = dojo.hitch(this, function() {
						this.__log("onUseragentChanged");
						
						this._removeEventListener('onUseragentChanged', listener);
						
						//run action
						var actionFinished = data.action ? data.action() : null;
						
						/* if action is deferred then call back this deferred after the action's
						 * deferred is called back.
						 * else callback this deferred now
						 */
						if(actionFinished instanceof dojo.Deferred) {
							actionFinished.addCallback(function() {
								deferred.callback();
							});
						} else {
							deferred.callback();
						}
					});
					this._addEventListener('onUseragentChanged', listener);
					
					// notify extension of change request
					dojo.attr(this._communicator, 'data-useragent', data.useragent);
					this._dispatchEvent('onUseragentChangeRequest');
				} else {
					this.__log("internalswitchUseragentID: switching not installed or not enabled");
					
					if(data.action) {
						data.action();
					}
					deferred.callback();
				}
				
				return deferred;
			};
			
			//add the new switch request to the queue of switch requests
			this._deferredSwitchs.push(dojo.hitch(this, internalswitchUseragentID));
			
			//if the deferred loop for processing the switch requests is not running then start it
			if(!this._deferredSwitchsLoopRunning) {
				this.__log("_switchUseragentID: start defferred switchs loop");
				
				this._deferredSwitchsLoopRunning = true;
				
				//this is a deferred loop that will processes each switch request one after the other
				var loop = function() {
					this.__log("_switchUseragentID: loop");
					
					if(this._deferredSwitchs[0]) {
						var deferred = this._deferredSwitchs[0]();
						deferred.addCallback(dojo.hitch(this,function() {
							this._deferredSwitchs.shift();
							dojo.hitch(this, loop)();
						}));
					} else {
						//loop has finished
						this._deferredSwitchsLoopRunning = false;
					}
				};
				
				//start the loop
				dojo.hitch(this, loop)();
			}
		},
		
		/**
		 * Used to dispatch an event.  Handles different browser APIs.
		 * 
		 * @param eventName {String} the name of the event to dispatch
		 */
		_dispatchEvent : function(eventName) {
			// different API for different browsers
			if(dojo.doc.createEvent) {
				var event = dojo.doc.createEvent('Event');
				event.initEvent(eventName, true, false);
				this._communicator.dispatchEvent(event);
			} else if(dojo.doc.createEventObject) {
				var event = dojo.doc.createEventObject();
				this._communicator.fireEvent(eventName, event);
			}
		},
		
		/**
		 * Adds an event listener to the communicator
		 * 
		 * @param eventName {String} name of event to listen for on the communicator
		 * @param func {Function} the function to run when notified of the event
		 */
		_addEventListener : function(eventName, func) {
			/* dojo.connect does not work here because communication is with extension point
			 * some versions of IE supports different api
			 */
			if(this._communicator.addEventListener) {
				this._communicator.addEventListener(eventName, func, true);
			} else if(this._communicator.attachEvent) {
				this._communicator.attachEvent(eventName, func, true);
			}
		},
		
		/**
		 * Removes an event listener fromt he communicator.
		 * 
		 * @param eventName {String} the name of the event to stop listening to on the communicator
		 * @param func {Function} the function that was listening to the event
		 */
		_removeEventListener : function(eventName, func) {
			/* dojo.disconnect does not work here because communication is with extension point
			 * some versions of IE supports different api
			 */
			if(this._communicator.removeEventListener) {
				this._communicator.removeEventListener(eventName, func, true);
			} else if(this._communicator.detachEvent) {
				this._communicator.detachEvent(eventName, func, true);
			}
		},
		
		/**
		 * <p>Used to log debugging messages</p>
		 * 
		 * @param msg
		 * @param args
		 */
		__log : function(msg, args) {
			if(this.__DEBUG_ENABLED) {
				msg = "UseragentSwitcherCommunicator: " + msg;
				console.log([msg, args]);
			}
		}
	}); //end dojo.declair
	
	return UseragentSwitcherCommunicator;
});
