/**

* Autoplay Plugin
* @version 2.3.4
* @author Bartosz Wojciechowski
* @author Artus Kolanowski
* @author David Deutsch
* @author Tom De Caluwé
* @license The MIT License (MIT)
*/

;(function($, window, document, undefined) {

/**
 * Creates the autoplay plugin.
 * @class The Autoplay Plugin
 * @param {Owl} scope - The Owl Carousel
 */
var Autoplay = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * The autoplay timeout id.
         * @type {Number}
         */
        this._call = null;

        /**
         * Depending on the state of the plugin, this variable contains either
         * the start time of the timer or the current timer value if it's
         * paused. Since we start in a paused state we initialize the timer
         * value.
         * @type {Number}
         */
        this._time = 0;

        /**
         * Stores the timeout currently used.
         * @type {Number}
         */
        this._timeout = 0;

        /**
         * Indicates whenever the autoplay is paused.
         * @type {Boolean}
         */
        this._paused = true;

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
                'changed.owl.carousel': $.proxy(function(e) {
                        if (e.namespace && e.property.name === 'settings') {
                                if (this._core.settings.autoplay) {
                                        this.play();
                                } else {
                                        this.stop();
                                }
                        } else if (e.namespace && e.property.name === 'position' && this._paused) {
                                // Reset the timer. This code is triggered when the position
                                // of the carousel was changed through user interaction.
                                this._time = 0;
                        }
                }, this),
                'initialized.owl.carousel': $.proxy(function(e) {
                        if (e.namespace && this._core.settings.autoplay) {
                                this.play();
                        }
                }, this),
                'play.owl.autoplay': $.proxy(function(e, t, s) {
                        if (e.namespace) {
                                this.play(t, s);
                        }
                }, this),
                'stop.owl.autoplay': $.proxy(function(e) {
                        if (e.namespace) {
                                this.stop();
                        }
                }, this),
                'mouseover.owl.autoplay': $.proxy(function() {
                        if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                                this.pause();
                        }
                }, this),
                'mouseleave.owl.autoplay': $.proxy(function() {
                        if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                                this.play();
                        }
                }, this),
                'touchstart.owl.core': $.proxy(function() {
                        if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                                this.pause();
                        }
                }, this),
                'touchend.owl.core': $.proxy(function() {
                        if (this._core.settings.autoplayHoverPause) {
                                this.play();
                        }
                }, this)
        };

        // register event handlers
        this._core.$element.on(this._handlers);

        // set default options
        this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
};

/**
 * Default options.
 * @public
 */
Autoplay.Defaults = {
        autoplay: false,
        autoplayTimeout: 5000,
        autoplayHoverPause: false,
        autoplaySpeed: false
};

/**
 * Transition to the next slide and set a timeout for the next transition.
 * @private
 * @param {Number} [speed] - The animation speed for the animations.
 */
Autoplay.prototype._next = function(speed) {
        this._call = window.setTimeout(
                $.proxy(this._next, this, speed),
                this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read()
        );

        if (this._core.is('interacting') || document.hidden) {
                return;
        }
        this._core.next(speed || this._core.settings.autoplaySpeed);
}

/**
 * Reads the current timer value when the timer is playing.
 * @public
 */
Autoplay.prototype.read = function() {
        return new Date().getTime() - this._time;
};

/**
 * Starts the autoplay.
 * @public
 * @param {Number} [timeout] - The interval before the next animation starts.
 * @param {Number} [speed] - The animation speed for the animations.
 */
Autoplay.prototype.play = function(timeout, speed) {
        var elapsed;

        if (!this._core.is('rotating')) {
                this._core.enter('rotating');
        }

        timeout = timeout || this._core.settings.autoplayTimeout;

        // Calculate the elapsed time since the last transition. If the carousel
        // wasn't playing this calculation will yield zero.
        elapsed = Math.min(this._time % (this._timeout || timeout), timeout);

        if (this._paused) {
                // Start the clock.
                this._time = this.read();
                this._paused = false;
        } else {
                // Clear the active timeout to allow replacement.
                window.clearTimeout(this._call);
        }

        // Adjust the origin of the timer to match the new timeout value.
        this._time += this.read() % timeout - elapsed;

        this._timeout = timeout;
        this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed);
};

/**
 * Stops the autoplay.
 * @public
 */
Autoplay.prototype.stop = function() {
        if (this._core.is('rotating')) {
                // Reset the clock.
                this._time = 0;
                this._paused = true;

                window.clearTimeout(this._call);
                this._core.leave('rotating');
        }
};

/**
 * Pauses the autoplay.
 * @public
 */
Autoplay.prototype.pause = function() {
        if (this._core.is('rotating') && !this._paused) {
                // Pause the clock.
                this._time = this.read();
                this._paused = true;

                window.clearTimeout(this._call);
        }
};

/**
 * Destroys the plugin.
 */
Autoplay.prototype.destroy = function() {
        var handler, property;

        this.stop();

        for (handler in this._handlers) {
                this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
                typeof this[property] != 'function' && (this[property] = null);
        }
};

$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;

})(window.Zepto || window.jQuery, window, document);