/*!
 * @copyright Advanced Care Solutions, Inc.
 * @author Christopher Rahauiser <crahauiser@acs-web.com>
 * @depends jquery.ui.widget.js
 */
(function($) {
  $.widget('acs.slideshow', {
    options: {
      autoPlay: true,

      timerDuration: 6000,

      prepareNext: function(animateInObj, animateOutObj) { },
      preparePrevious: function(animateInObj, animateOutObj) { },
      childrenSetup: function(children) { },

      animateInNextEasing: 'swing',
      animateInNextDuration: 1200,
      animateInNextProperties: { opacity: 'toggle' },
      animateInNextCallback: function() {
        $(this).css('z-index', 2);
      },

      animateOutNextEasing: 'swing',
      animateOutNextDuration: 1200,
      animateOutNextProperties: { opacity: 'toggle' },
      animateOutNextCallback: function() {
        $(this).css('z-index', 1);
      },

      animateInPreviousEasing: 'swing',
      animateInPreviousDuration: 1200,
      animateInPreviousProperties: { opacity: 'toggle' },
      animateInPreviousCallback: function() {
        $(this).css('z-index', 2);
      },

      animateOutPreviousEasing: 'swing',
      animateOutPreviousDuration: 1200,
      animateOutPreviousProperties: { opacity: 'toggle' },
      animateOutPreviousCallback: function() {
        $(this).css('z-index', 1);
      },

      nextSelector: '.acs-slideshow-next',
      previousSelector: '.acs-slideshow-previous',
      playPauseSelector: '.acs-slideshow-play-pause',
      playClass: 'acs-slideshow-play',
      pauseClass: 'acs-slideshow-pause'
    },
    timer: null,
    animating: false,
    children: $([]),
    playPauseControls: $([]),
    nextControls: $([]),
    previousControls: $([]),
    _current: 0,
    _next: 1,
    play: function(suppressEvent) {
      if (this.options.disabled) {
        return;
      }

      if (! suppressEvent && this._trigger('beforePlay') === false) {
        return;
      }

      this.playPauseControls
        .addClass(this.options.pauseClass)
        .removeClass(this.options.playClass);
      this.timer = setInterval($.proxy(this.next, this),
        this.options.timerDuration);

      if (! suppressEvent) {
        this._trigger('play');
      }
    },
    pause: function(suppressEvent) {
      if (this.options.disabled) {
        return;
      }

      if (! suppressEvent && this._trigger('beforePause') === false) {
        return;
      }
      clearInterval(this.timer);
      this.timer = null;

      this.playPauseControls
        .addClass(this.options.playClass)
        .removeClass(this.options.pauseClass);

      if (! suppressEvent) {
        this._trigger('pause');
      }
    },
    next: function() {
      if (this.options.disabled) {
        return;
      }

      if (this.animating) {
        return;
      }

      if (this._trigger('beforeNext') === false) {
        return;
      }

      this.animating = true;

      this.pause(true); // stop rotation

      this._next = this._current + 1;
      if (this._next == this.children.length) {
        this._next = 0;
      }

      this.options.prepareNext(this.children.eq(this._next),
        this.children.eq(this._current));

      var self = this;

      this.children
        .eq(this._next)
          .animate(
            this.options.animateInNextProperties,
            this.options.animateInNextDuration,
            this.options.animateInNextEasing,
            this.options.animateInNextCallback
          )
        .end()
        .eq(this._current)
          .animate(
            this.options.animateOutNextProperties,
            this.options.animateOutNextDuration,
            this.options.animateOutNextEasing,
            function() {
              self.options.animateOutNextCallback.call(this); // set this to dom element
              self.animating = false;
              self._trigger('next');
            }
          );
      this._current = this._next;

      this.play(true); // startup rotation
    },
    previous: function() {
      if (this.options.disabled) {
        return;
      }

      if (this.animating) {
        return;
      }

      if (this._trigger('beforePrevious') === false) {
        return;
      }

      this.animating = true;

      this.pause(true); // stop rotation

      this._next = this._current - 1;
      if (this._next < 0) {
        this._next = this.children.length - 1;
      }

      this.options.preparePrevious(this.children.eq(this._next),
        this.children.eq(this._current));

      var self = this;

      this.children
        .eq(this._next)
          .animate(
            this.options.animateInPreviousProperties,
            this.options.animateInPreviousDuration,
            this.options.animateInPreviousEasing,
            this.options.animateInPreviousCallback
          )
        .end()
        .eq(this._current)
          .animate(
            this.options.animateOutPreviousProperties,
            this.options.animateOutPreviousDuration,
            this.options.animateOutPreviousEasing,
            function() {
              self.options.animateOutPreviousCallback.call(this); // set this to dom element
              self.animating = false;
              self._trigger('previous');
            }
          );
      this._current = this._next;

      this.play(true); // startup rotation
    },
    enable: function() {
      $.Widget.prototype.enable.apply(this, arguments);
      this._init();
    },
    disable: function() {
      $.Widget.prototype.disable.apply(this, arguments);
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
    },
    destroy: function() {
      if (this.timer) {
        clearInterval(this.timer);
        this.timer = null;
      }
      this.playPauseControls.hide().unbind('.slideshow');
      this.nextControls.hide().unbind('.slideshow');
      this.previousControls.hide().unbind('.slideshow');
      this.children
        .eq(0)
          .show()
        .end()
        .not(':eq(0)')
          .hide()
        .end()
        .css({
          top: 0,
          left: 0
        });
      $.Widget.prototype.destroy.apply(this, arguments);
    },
    _create: function() {
      this.children = this.element.children();
      if (this.children.length > 1) {
        this.options.childrenSetup(this.children);
      }
      this.playPauseControls =
          $(this.options.playPauseSelector)
            .show()
            .bind('click.slideshow', $.proxy(this._playPauseClick, this));
      this.nextControls =
          $(this.options.nextSelector)
            .show()
            .bind('click.slideshow', $.proxy(this._nextClick, this));
      this.previousControls =
          $(this.options.previousSelector)
            .show()
            .bind('click.slideshow', $.proxy(this._previousClick, this));
    },
    _init: function() {
      if (this.options.autoPlay) {
        this.play();
      }
    },
    _playPauseClick: function(event) {
      event.preventDefault();
      if (this.playPauseControls.hasClass(this.options.pauseClass)) {
        this.pause();
      } else {
        this.play();
      }
    },
    _nextClick: function(event) {
      event.preventDefault();
      this.next();
    },
    _previousClick: function(event) {
      event.preventDefault();
      this.previous();
    }
  });
})(jQuery);
