/**
 * Session timeout warning / extension plug-in.
 * 
 * Depends on:
 *  - jquery (1.5.1 or greater)
 *  - jquery-ui (1.8.11 or greater, javascript and css)
 *
 * Author: Andrew Pitt
 * @since 2.2
 */
(function( $ ){      
    // Multiplier to get minutes in millies: 60 sec/min * 1000 millis/sec.
    var minuteMultiplier = 60 * 1000;

    // Holds the timeout ID in case timeout needs to be canceled.
    var warningTimeoutId = null;
    var countdownTimeoutId = null;
    var intervalId = null;
    var intervalCount = 0;

    // Dialog div ID and selector.
    var dialogId = "timeout-warning-dialog";
    var dialogSelector = '#' + dialogId;

    /**
     * Get the users current language based on the lang attribute of the html tag.
     * @return <code>String</code>
     */
    var getLang = function() {
        return $('html').attr('lang').substr(0,2).toUpperCase();
    };
    
    /**
     * Function to be called when the "OK" or "X" button are clicked after the session has expired.
     * @param event <code>Object</code>
     * @param ui <code>Object</code>
     */
    var expiredSessionCloseEvent = function(event, ui) { 
        $(dialogSelector).dialog('destroy');
        $(dialogSelector).remove();

        if (window.globalTimeoutOptions['locationOnExpiry']) {
        	window.location = window.globalTimeoutOptions['locationOnExpiry'];
        } else {
        	window.location.reload();
        }        	
    };
    
    /**
     * Tick off another minute from the session timeout count displayed in the dialog.
     */
    var tick = function() {
        window.minutesToTimeout = window.minutesToTimeout - 1;
        if (window.minutesToTimeout != 0) {
            $('#timeoutMins').html(window.minutesToTimeout);
            countdownTimeoutId = window.setTimeout(function() {
                tick();
            }, minuteMultiplier);
        } else if (window.minutesToTimeout == 0) {
            var sessionDialog = $(dialogSelector);
            sessionDialog.find('p').html(window.globalTimeoutOptions['timedOutText' + getLang()]);

            // Ensure timeout is enforced by pinging the logout url for apps that use authentication.
            if (window.globalTimeoutOptions['logoutUrl']) {
            	$.get(window.globalTimeoutOptions['logoutUrl'], function() {console.log("Logged out by session timeout dialig.");});
            }
            
            sessionDialog.dialog("option" , {
                close: expiredSessionCloseEvent,
                click: expiredSessionCloseEvent
            });
        }
    };
    
    /**
     * Function that is called once the timeout has been triggered.
     * This will create and display the timeout warning dialog.
     */
    var triggerTimeoutWarning = function() {
        var settings = window.globalTimeoutOptions;
        
        // Language.
        var lang = getLang();

        // Start the countdown timer.        
        countdownTimeoutId = window.setTimeout(function() {
            tick();
        }, minuteMultiplier);                
                
        // Create the dialog and display it.
        $('body').append("<div id=\"" + dialogId + "\" title=\"" + settings['title' + lang] + "\"><p>" + settings['text' + lang] + "</p></div>");
        $('#timeoutMins').html(window.minutesToTimeout);
        settings['buttons'] = [{
                text: settings['buttonText' + lang],
                click: function() { 
                    $.get(settings['keepAliveUrl'], function() { 
                        window.clearTimeout(countdownTimeoutId);
                        $.sessionTimeout(window.globalTimeoutOptions);
                    });
                    $(dialogSelector).dialog('close');
                }
            }];        
        $(dialogSelector).dialog(settings);        
    };
    
    /**
     * Session Timeout jQuery function.
     * @param options <code>Object</code>
     * @return <code>Object</code> - jQuery object for chaining.
     */    
    $.sessionTimeout = function(options) {                 
        var settings = window.globalTimeoutOptions;
        if (typeof(settings) == 'undefined') {
            // Default settings, overridden by options.
            settings = $.extend({
                // jQuery-ui options.
                modal: true,
                width: 500,
                close: function(event, ui) { $(dialogSelector).dialog('destroy'); $(dialogSelector).remove(); window.clearTimeout(countdownTimeoutId); },
                // Options specific to timeout warning.
                timeoutInMinutes: 30,
                minutesUntilTimeout: 5,
                titleEN: 'Session Timeout',
                titleFR: 'Délai d\'inactivité',
                textEN: 'Your session will expire in <span id="timeoutMins"></span>&nbsp;minutes.  Need more time? Click "OK" to continue.',
                textFR: 'Votre session expirera dans <span id="timeoutMins"></span>&nbsp;minutes.  Vous avez besoin de plus de temps? Cliquez sur « OK » pour continuer.',
                timedOutTextEN: 'For security reasons, your session timed out due to inactivity. You will be redirected to the login page.',
                timedOutTextFR: 'Pour des raisons de sécurité, votre session a été interrompue en raison d\'une période d\'inactivité. Vous serez redirigé(e) vers la page d\'ouverture de session.',
                buttonTextEN: 'OK',
                buttonTextFR: 'OK'
                /* optional:
                ,locationOnExpiry - url to be used instead of reloading the current expired page
                */
            }, options);
            
            window.globalTimeoutOptions = settings;            
        }
        
        // Register the # of minutes until the timeout as a global variable.
        window.minutesToTimeout = settings['minutesUntilTimeout'];

        warningTimeoutId = window.setTimeout(function() {
            triggerTimeoutWarning();
        }, (settings['timeoutInMinutes'] - settings['minutesUntilTimeout']) * minuteMultiplier);
    };   
    
    // Initialization object.
    initializers.sessionTimeout = {
        init: function(callback) { 
            console.info("PE-SessionTimeout: Initializing.");
            this.afterDependenciesLoaded = callback;
            this.afterDependenciesLoaded();
        },        
        afterDependenciesLoaded: function() { 
            console.info("PE-SessionTimeout: afterDependenciesLoaded function not set."); 
        }
    };      

})( jQuery );

