/*
 * This class will generate warning alerts when the user session is about to time out.
 * by default the class will only initialized.
 * The timeouts will be started/reset with the method stillAlive()
 * there are two timeouts:
 * 		timeoutWarning:  This will show a warning dialog to indicate the user that his 
 *                       session is about to expire
 *      timeoutExpired:  This will show a dialog informing the user that his session is
 *                       now expired.  The user will be forcefully logged off from the 
 *                       DW server.
 * If the user closes the Warning dialog, the session will be renewed and the timer reset.
 * If the user closes the Expired dialog, the browser might be redirected to a login page.
 * 
 * Configuration variables:
 * sessionMonitor.timeWarning         // delay for the warning in seconds, referencing the last alive signal
 * sessionMonitor.timeExpired         // delay for the logout in seconds, referencing the last alive signal
 * sessionMonitor.pollStatus          // when dialog shows that the user is logged out, check every n sec if 
 *                                       logged in in a different browser window 
 * sessionMonitor.timeoutWarning      // text shown for the warning
 * sessionMonitor.timeoutExpired      // text shown for the session expired
 * sessionMonitor.terminatedExtern    // the session got terminated before this timeout kicked in
 * sessionMonitor.timeoutDlgTitle     // title of the hopup dialog
 * sessionMonitor.keepAliveURL        // if the user sees the warning dialog and presses "ESC", send an alive signal to the server
 * sessionMonitor.logoffURL           // go here to logout the current user
 * sessionMonitor.goAfterLogoutURL    // if this is set to boolean true (NOT String "true"), the page will be
 *                                       reloaded after the user closes the Expired dialog
 *                                       If the value is a String, it must contain the full HTTP URL.
 *                                       the user will be redirected to this URL after the the user 
 *                                       closes the dialog
 * sessionMonitor.userStatusChangedAction // this can be a JS function to be called when when the user status changes
 *                                       from either logged in to logged out or vice versa, e.g. update the page header
 */
var __sessionMonitor2 =  {

	/**
	 * reference to the timeout object of the document
	 */
	timeoutObj : null,
	
	/**
	 * class of the DIV conatiner
	 */
	timeoutDiv : "timeoutContainer",
	
	/**
	 * this is to make sure it is not undefined
	 */
	goAfterLogoutURL: null,
	
	/**
	 * what to do if user status changes, e.g. update header.
	 */
	 userStatusChangedAction: null,

	/**
	 * his variable will be set to <true> in case the session
	 * monitor itself makes call.  This can be the case when 
	 * we need to fund out if we are still alive.
	 */
	internalCall: false,
	
	/**
	 * this listener listens in into every external jQuery JSON request
	 * if the timer is already going, the status will be updated
	 */
	ajaxSuccessLisener: function( target, xhr, settings ){
		// jQuery( document ).bind( 'ajaxComplete', sessionMonitor.ajaxCompleteLisener );
		if ( 
				!sessionMonitor.internalCall      // not a call from the session manager
				&&
				sessionMonitor.timeoutObj != null          // and we are interested in possible timeouts 
				&& 
				'json' == settings.dataType       // and it is a json request 
			)
		{
			var data = jQuery.httpData( xhr, settings.dataType, settings );
			if (data != null && ("authenticated" in data ))
			{
				
				sessionMonitor.stillAlive( data.authenticated );
			}
			// alert( 'ajaxDone' );
		}
	},
	
	/**
	 * this method evaluates/executes that script that can 
	 * be defined in the attribute userStatusChangedAction
	 */
	__userLoginSatusChanged: function( isLoggedIn )
	{
		if ( sessionMonitor.userStatusChangedAction )
		{
			if ( typeof sessionMonitor.userStatusChangedAction == 'string' )
			{
				eval( sessionMonitor.userStatusChangedAction );
			}
			else
			{
				sessionMonitor.userStatusChangedAction( isLoggedIn );
			}
		}
	},
	
	stillAlive: function( isAlive ){
		if ( (typeof isAlive == 'undefined') || (isAlive==true) )
		{
			// alert( 'starting' );
			if ( this.timeoutObj != null )
			{
				// alert( 'resetting' );
				clearTimeout( this.timeoutObj );
			}
			this.timeoutObj = setTimeout( "sessionMonitor.__showAlert( 1 )", this.timeWarning * 1000 );
		}
		else
		{
			// here, we got notified that the user is definitely not logged in
			if ( this.timeoutObj != null )
			{
				// but if we had a timer running, then we 
				// definitely were at one time in a logged-in state 
				// with this page.  The user might have logged out
				// on a different browser window.
				clearTimeout( this.timeoutObj );
				this.timeoutObj = null;
				sessionMonitor.__showAlert( 3 );  // show "you've been logged of in a different window"
			}
		}
	},
	
	handleLoginState: function( data ){
		if ( data )
		{
			if ( data.authenticated )
			{
				sessionMonitor.stillAlive();
			}
			else
			{
				if ( sessionMonitor.timeoutObj )
				{
					clearTimeout( sessionMonitor.timeoutObj );
					sessionMonitor.timeoutObj = null;
				}
			}
		}
	},
	
	dialogIsClosing: function (){
		var jqId = '#' + this.timeoutDiv;
		// the user closed the dialog. To avoid multiple calls remove this function
		jQuery( jqId ).unbind( "dialogclose", sessionMonitor.dialogIsClosing );
		// send alive signal to server
		sessionMonitor.internalCall = true;
		app.ajax.getJson( {
			url: sessionMonitor.keepAliveURL,
			callback: function( data ){
				sessionMonitor.internalCall = false;
				// by default we should have this attirbute in the container
				// but FF3 has an issue when hopup and ESC pressed.  then we have the attribute Success set to false
				// a 2nd call will fix this
				if ( "authenticated" in data )
				{
					sessionMonitor.handleLoginState( data );
				}
				else
				{
					if ( "Success" in data && data.Success == false )
					{
						// FF3 has an issue when hopup and ESC pressed.  A 2nd call would work
						sessionMonitor.internalCall = true;
						app.ajax.getJson( {
							url: sessionMonitor.keepAliveURL,
							callback: function( data ){
							sessionMonitor.internalCall = false;
								if ( "authenticated" in data )
								{
									sessionMonitor.handleLoginState( data );
								}
							}
						});
					}
				}
			}
		});
	},

	__showAlert: function( dialogStatus ){
		
		var self = this;
		var jqId = '#' + self.timeoutDiv;
		if ( jQuery( jqId ).length == 0 )
		{
			jQuery(document.body).append("<div id='" + self.timeoutDiv + "' class='quickview sessionTimeout'></div>");
			jQuery( jqId ).dialog({
				title: self.timeoutDlgTitle, 
				autoOpen: false,
				modal: true,
				zIndex: 9990,
				width: 460,
				overlay: {
		    		opacity: 0.9,
		     		background: "#666666"
				},
		    	// height: myOptions.outerHeight ? myOptions.outerHeight : 425,
		    	// width: myOptions.outerWidth ? myOptions.outerWidth : 460,
		    	resizable: false
			});
			jQuery(".ui-dialog-titlebar").addClass(' sessionTimeout-header');
		}
		
		if ( !self.__isUserLoggedin() )
		{
			// we are supposed to show a warning here but the user is already logged of????
			dialogStatus = 3;
		}
		// we already process the timeout event.  No further calls needed
		if ( this.timeoutObj != null )
		{
			clearTimeout( this.timeoutObj );
			this.timeoutObj = null;
		}
		if ( dialogStatus == 1 )
		{
			
			// set the text to show
			jQuery( jqId ).html( self.timeoutWarning );
			// show the dialog
			jQuery( jqId ).dialog( 'open' );
			// set the time for the expiration
			self.timeoutObj = setTimeout( "sessionMonitor.__showAlert( 2 )", ( self.timeExpired - self.timeWarning) * 1000 );
			// if the user interacts with the dialog, we will send another alive signal to the server
			jQuery( jqId ).bind( "dialogclose", self.dialogIsClosing );
					
		}
		else
		{
			// the user didn't close the dialog, he won't get a second chance 
			jQuery( jqId ).unbind( "dialogclose", self.dialogIsClosing );
			// set the error message
			if ( dialogStatus == 2 )
			{
				// session timed out
				jQuery( jqId ).html( self.timeoutExpired );
				// show dialog
				jQuery( jqId ).dialog( 'open' );
				// log user off
				self.internalCall = true;
				app.ajax.getJson( {
					url: self.logoffURL,
					async: false,              // force to wait till the call is completed
					callback: function(){
						// the user is now logged off - update the header
						self.internalCall = false;
						sessionMonitor.__userLoginSatusChanged( false );
					}
				});
			}
			else
			{
				// session terminated in another browser window
				// update the header once we detect the user is logged 
				sessionMonitor.__userLoginSatusChanged( false );
				// update the dialog content
				jQuery( jqId ).html( self.terminatedExtern );
				// show dialog
				jQuery( jqId ).dialog( 'open' );
			}
			
			var sessionRestored = false;
			var __dialogCloing = function(){
				if ( !self.__isUserLoggedin() )  // test if he restored the session in a different window!
				{
					if ( self.goAfterLogoutURL != null )
					{
						// here we have (most likely) the same issue as we
						// had when sending the alive signal to the server.
						// when the dialog was closed via ESC, the simple
						// assignment will not work in the current context.
						if ( (self.goAfterLogoutURL instanceof Boolean) || (typeof self.goAfterLogoutURL == "boolean" ) )
						{
							// we could use reload() here but that would annoy in 
							// case of a previous POST.  Since the user should be 
							// directed to the starting page of the current process
							// anyways, I prefer this GET
							setTimeout( "window.location = window.location", 13 );  
						}
						else
						{
							setTimeout( "window.location = sessionMonitor.goAfterLogoutURL", 13 );
						}
					}
				}
			};
			// if we got here, poll every n seconds to see if the session was restored somewhere else
			var pollThread = setInterval( function(){ 
				if ( self.__isUserLoggedin() )
				{
					sessionMonitor.__userLoginSatusChanged( true );          // show the header as logged in again
					clearInterval( pollThread );                              // no more polling
					jQuery( jqId ).unbind( "dialogclose", __dialogCloing );   // to avoid redirects from closing the dialog
					jQuery( jqId ).dialog( 'close' );                         // and gone, close the dialog
					sessionMonitor.stillAlive( true );                       // restart the timer
					
				}
			}, self.pollStatus * 1000 );
			jQuery( jqId ).bind( "dialogclose", __dialogCloing );
		}
	},
	
	/*
	 * quickly ask if the user is currently logged in
	 */
	__isUserLoggedin: function(){
		var self = this;
		var ret = false;
		self.internalCall = true;
		app.ajax.getJson( {
			url: self.keepAliveURL,
			async: false,
			callback: function( data ){
				self.internalCall = false;
				// by default we should have this attirbute in the container
				// but FF3 has an issue when hopup and ESC pressed.  then we have the attribute Success set to false
				// a 2nd call will fix this
				if ( "authenticated" in data )
				{
					ret = data.authenticated;
				}
			}
		});
		return ret;
	},
	
	init: function()
	{
		// alert( 'in init' );
		jQuery( document ).bind( 'ajaxSuccess', this.ajaxSuccessLisener );
	}
};
//there were some issues reported regarding timing issues in IE6
//it could happen that this script was executed before the sessionMonitor script
//had been executed.  This is trying to make up for this case
if ( typeof sessionMonitor != 'undefined' )
{
	sessionMonitor = jQuery.extend( __sessionMonitor2, sessionMonitor );
}
else
{
	sessionMonitor = __sessionMonitor2;
}
delete __sessionMonitor2;
sessionMonitor.init();

/**
 * this function takes a JS function that will be executed 
 * after it was determined that the user was authenticated.
 * If user is currently not logged in, he will see a dialog
 * asking him to provide his login or create a new account.
 * @param dialogTitle - login dialog title 
 * @param loginParams - optional parameters to pass to the 
 *         login URL
 * @param executeAfterLogin - this function will be executed after 
 *                the user is authenticated
 * @param executeAfterCancel - this optional function will be 
 *                executed if during the log in process the user
 *                closes the login dialog
 * @return - true if user is already authenticated or can be 
 *                authenticated via hopup
 *                if not, the code itself must redirect to a full
 *                page load for he desired interaction
 */
function executeAsAuthCustomer( dialogTitle, executeAfterLogin, forceRedirect, executeAfterCancel, loginParams )
{

	if ( typeof executeAfterCancel != 'function' && loginParams == null )
	{
		loginParams = executeAfterCancel;
		executeAfterCancel = null;
	}
	var url = sessionMonitor.keepAliveURL;
	var canDoAuthAction = true;
	
	var result = app.ajax.getJson({
		url: url,
		async: false,
		callback: function(data) {
			if( data && data.authenticated ) {
				// just do the adding
				executeAfterLogin();
			} else {
				hopupCustomerAuthenticated = false;
				// either no data or not logged in
				// test if we can show popup dialog
				if ( window.location.protocol == "https:" && !forceRedirect)
				{
					// we are on a HTTPS connection -> we can show a login dialog
					if ( loginParams )
						hopupLoginURL += '?' + jQuery.param( loginParams );
					
					app.dialog.open(
							hopupLoginURL, 
							dialogTitle, 
							"customerLogin", 
							{innerWidth: 450, outerWidth: 534, innerHeight:'auto', outerHeight: 'auto' } 
							// {innerWidth: 850, outerWidth: 750, innerHeight:'auto' } 
						);
					

					var afterMess = new (function( param ){
						var self = this;
						this.executeAfterLogin = param;
						this.ajaxCompleteLisener = function ()
						{
							if ( typeof hopupCustomerAuthenticated != 'undefined' )
							{
								// alert( ' data loaded ' + hopupCustomerAuthenticated);
								if ( hopupCustomerAuthenticated )
								{
									app.dialog.close();  // that also should take care for the listener
									// once we are quthenticated we no longer care about
									// about the notification.  just kill the listener
									// jQuery('#dialogcontainer').unbind( 'ajaxComplete', self.ajaxCompleteLisener );
									bui.updateUserDataInHeader();
									self.executeAfterLogin();
								}
							}
							else
							{
								// alert( 'hopupCustomerAuthenticated undefined' );
							}
						} 

						this.dialogCloseLisener = function()
						{
							// alert( 'removing' );
							// we no longer need the window close event
							jQuery('#dialogcontainer').unbind( 'dialogclose', self.dialogCloseLisener );
							jQuery('#dialogcontainer').unbind( 'ajaxComplete', self.ajaxCompleteLisener );
							if ( executeAfterCancel )
								executeAfterCancel();
						}
						
					})(executeAfterLogin); 

					// whatever happens in the dialog, I don't care.  I only need
					// to see if the if the variable hopupCustomerAuthenticated is set to <true>
					jQuery('#dialogcontainer').bind( 'ajaxComplete', afterMess.ajaxCompleteLisener ); 
					// when we close the dialog, we no longer need to listen to the 
					// Ajax requests.
					jQuery('#dialogcontainer').bind( 'dialogclose', afterMess.dialogCloseLisener ); 
				}
				else
				{
					canDoAuthAction = false;
				}
			}
		}
	});
	return canDoAuthAction;
}

