// Caption module for Slider Pro.
// 
// Adds a corresponding caption for each slide. The caption
// will appear and disappear with the slide.
;(function( window, $ ) {

	"use strict";
	
	var NS = 'Caption.' + $.SliderPro.namespace;

	var Caption = {

		// Reference to the container element that will hold the caption
		$captionContainer: null,

		// The caption content/text
		captionContent: '',

		initCaption: function() {
			this.on( 'update.' + NS, $.proxy( this._captionOnUpdate, this ) );
			this.on( 'gotoSlide.' + NS, $.proxy( this._updateCaptionContent, this ) );
		},

		// Create the caption container and hide the captions inside the slides
		_captionOnUpdate: function() {
			this.$captionContainer = this.$slider.find( '.sp-caption-container' );

			if ( this.$slider.find( '.sp-caption' ).length && this.$captionContainer.length === 0 ) {
				this.$captionContainer = $( '<div class="sp-caption-container"></div>' ).appendTo( this.$slider );

				// Show the caption for the selected slide
				this._updateCaptionContent();
			}

			// Hide the captions inside the slides
			this.$slides.find( '.sp-caption' ).each(function() {
				$( this ).css( 'display', 'none' );
			});
		},

		// Show the caption content for the selected slide
		_updateCaptionContent: function() {
			var that = this,
				newCaptionField = this.$slider.find( '.sp-slide' ).eq( this.selectedSlideIndex ).find( '.sp-caption' ),
				newCaptionContent = newCaptionField.length !== 0 ? newCaptionField.html() : '';

			// Either use a fade effect for swapping the captions or use an instant change
			if ( this.settings.fadeCaption === true ) {
				
				// If the previous slide had a caption, fade out that caption first and when the animation is over
				// fade in the current caption.
				// If the previous slide didn't have a caption, fade in the current caption directly.
				if ( this.captionContent !== '' ) {

					// If the caption container has 0 opacity when the fade out transition starts, set it
					// to 1 because the transition wouldn't work if the initial and final values are the same,
					// and the callback functions wouldn't fire in this case.
					if ( parseFloat( this.$captionContainer.css( 'opacity' ), 10 ) === 0 ) {
						this.$captionContainer.css( this.vendorPrefix + 'transition', '' );
						this.$captionContainer.css( 'opacity', 1 );
					}

					this._fadeCaptionTo( 0, function() {
						that.captionContent = newCaptionContent;

						if ( newCaptionContent !== '' ) {
							that.$captionContainer.html( that.captionContent );
							that._fadeCaptionTo( 1 );
						} else {
							that.$captionContainer.empty();
						}
					});
				} else {
					this.captionContent = newCaptionContent;
					this.$captionContainer.html( this.captionContent );
					this.$captionContainer.css( 'opacity', 0 );
					this._fadeCaptionTo( 1 );
				}
			} else {
				this.captionContent = newCaptionContent;
				this.$captionContainer.html( this.captionContent );
			}
		},

		// Fade the caption container to the specified opacity
		_fadeCaptionTo: function( opacity, callback ) {
			var that = this;

			// Use CSS transitions if they are supported. If not, use JavaScript animation.
			if ( this.supportedAnimation === 'css-3d' || this.supportedAnimation === 'css-2d' ) {
				
				// There needs to be a delay between the moment the opacity is set
				// and the moment the transitions starts.
				setTimeout(function(){
					var css = { 'opacity': opacity };
					css[ that.vendorPrefix + 'transition' ] = 'opacity ' + that.settings.captionFadeDuration / 1000 + 's';
					that.$captionContainer.css( css );
				}, 1 );

				this.$captionContainer.on( this.transitionEvent, function( event ) {
					if ( event.target !== event.currentTarget ) {
						return;
					}

					that.$captionContainer.off( that.transitionEvent );
					that.$captionContainer.css( that.vendorPrefix + 'transition', '' );

					if ( typeof callback === 'function' ) {
						callback();
					}
				});
			} else {
				this.$captionContainer.stop().animate({ 'opacity': opacity }, this.settings.captionFadeDuration, function() {
					if ( typeof callback === 'function' ) {
						callback();
					}
				});
			}
		},

		// Destroy the module
		destroyCaption: function() {
			this.off( 'update.' + NS );
			this.off( 'gotoSlide.' + NS );

			this.$captionContainer.remove();

			this.$slider.find( '.sp-caption' ).each(function() {
				$( this ).css( 'display', '' );
			});
		},

		captionDefaults: {

			// Indicates whether or not the captions will be faded
			fadeCaption: true,

			// Sets the duration of the fade animation
			captionFadeDuration: 500
		}
	};

	$.SliderPro.addModule( 'Caption', Caption );
	
})( window, jQuery );