﻿(function ($) {

    $.idleTimeout = function (element, resume, options) {

        // overwrite $.idleTimeout.options with the results of $.extend.  Allows you to write and a callback then call it from 
        // from a jQuery UI button or something
        options = $.idleTimeout.options = $.extend({}, $.idleTimeout.options, options);

        var IdleTimeout = {
            init: function () {
                var self = this;

                this.warning = $(element);
                this.resume = $(resume);
                this.countdownOpen = false;
                this.failedRequests = options.failedRequests;
                this._startTimer();

                // start the idle timer
                $.idleTimer(options.idleAfter * 1000);

                // once the user becomes idle
                $(document).bind("idle.idleTimer", function () {

                    // if the user is idle and a countdown isn't already running
                    if ($.data(document, 'idleTimer') === 'idle' && !self.countdownOpen) {
                        self._stopTimer();
                        self.countdownOpen = true;
                        self._idle();
                    }
                });

                // bind continue link
                this.resume.bind("click", function (e) {
                    e.preventDefault();

                    window.clearInterval(self.countdown); // stop the countdown
                    self.countdownOpen = false; // stop countdown
                    self._startTimer(); // start up the timer again
                    options.onResume.call(self.warning); // call the resume callback
                });
            },

            _idle: function () {
                var self = this,
					warning = this.warning[0],
					counter = options.warningLength;

                // fire the onIdle function
                options.onIdle.call(warning);

                // set inital value in the countdown placeholder
                options.onCountdown.call(warning, counter);

                // create a timer that runs every second
                this.countdown = window.setInterval(function () {
                    counter -= 1;

                    if (counter === 0) {
                        window.clearInterval(self.countdown);
                        options.onTimeout.call(warning);
                    } else {
                        options.onCountdown.call(warning, counter);
                    }

                }, 1000);
            },

            _startTimer: function () {
                var self = this;

                this.timer = window.setInterval(function () {
                    self._keepAlive();
                }, options.pollingInterval * 1000);
            },

            _stopTimer: function () {
                // reset the failed requests counter
                this.failedRequests = options.failedRequests;

                // stop the timer
                window.clearInterval(this.timer);
            },

            _keepAlive: function () {
                var self = this;

                // if too many requests failed, abort
                if (!this.failedRequests) {
                    this._stopTimer();
                    options.onAbort.call(this.element);
                    return;
                }

                $.ajax({
                    timeout: options.AJAXTimeout,
                    url: options.keepAliveURL,
                    error: function () {
                        self.failedRequests--;
                    },
                    success: function (response) {

                        // the response from the server must equal OK
                        if ($.trim(response) !== options.serverResponseEquals) {
                            self.failedRequests--;
                        }
                    }
                });
            }
        };

        // run this thang
        IdleTimeout.init();
    };

    $.idleTimeout.options = {
        // number of seconds after user is idle to show the warning
        warningLength: 30,

        // url to call to keep the session alive while the user is active
        keepAliveURL: "",

        // the response from keepAliveURL must equal this text:
        serverResponseEquals: "OK",

        // user is considered idle after this many seconds.  10 minutes default
        idleAfter: 600,

        // a polling request will be sent to the server every X seconds
        pollingInterval: 60,

        // number of failed polling requests until we abort this script
        failedRequests: 5,

        // the $.ajax timeout in MILLISECONDS! 
        AJAXTimeout: 250,

        /*
        Callbacks
        "this" refers to the #idletimthis.failedRequests = options.failedRequests;eout element.
        */
        // callback to fire when the session is resumed (by clicking the resume link)
        onTimeout: function () { },

        // fires when the user becomes idle
        onIdle: function () { },

        // fires during each second of warningLength
        onCountdown: function () { },

        // fires when the user resumes the session
        onResume: function () { },

        // callback to fire when the script is aborted due to too many failed requests
        onAbort: function () { }
    };

})(jQuery);
