/* ========================================================================
 * VC: carousel.js v0.4.5
 * Fork Bootstrap: carousel.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#carousel
 * ========================================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================================== */

( function ( $ ) {
	'use strict';

	// CAROUSEL CLASS DEFINITION
	// =========================

	function Carousel ( element, options ) {
		this.$element = $( element );
		this.$indicators = this.$element.find( '.vc_carousel-indicators' );
		this.options = options;
		this.paused =
			this.sliding =
				this.interval =
					this.$active =
						this.$items = null;
		if ( 'hover' === this.options.pause ) {
			this.$element
				.on( 'mouseenter', $.proxy( this.pause, this ) )
				.on( 'mouseleave', $.proxy( this.cycle, this ) );
		}
		this._build(); // new
	}

	Carousel.DEFAULTS = {
		mode: 'horizontal',
		partial: false,
		interval: 5000,
		pause: 'hover',
		wrap: false,
		autoHeight: false,
		perView: 1
	};
	Carousel.prototype.cycle = function ( e ) {
		if ( !e ) {
			this.paused = false;
		}

		if ( this.interval ) {
			clearInterval( this.interval );
		}

		if ( this.options.interval && !this.paused ) {
			this.interval = setInterval( $.proxy( this.next, this ), this.options.interval );
		}
		this.touch_start_position = 0;
		return this;
	};
	Carousel.prototype.getActiveIndex = function () {
		this.$active = this.$element.find( '.vc_item.vc_active' );
		if ( !this.$active.length ) {
			this.$active = this.$element.find( '.vc_item:first' ).addClass( 'vc_active' );
		}
		this.$items = this.$active.parent().children();
		return this.$items.index( this.$active );
	};
	Carousel.prototype.showHideControl = function ( index ) {
		if ( 'undefined' === typeof ( index ) ) {
			index = this.getActiveIndex();
		}
		this.$left_control[ 0 === index ? 'hide' : 'show' ]();
		this.$right_control[ index === this.items_count - 1 ? 'hide' : 'show' ]();
	};
	Carousel.prototype.to = function ( pos ) {
		var that = this;
		var activeIndex = this.getActiveIndex();

		if ( pos > ( this.$items.length - 1 ) || 0 > pos ) {
			return;
		}

		if ( this.sliding ) {
			return this.$element.one( 'slid', function () {
				that.to( pos );
			});
		}
		if ( activeIndex == pos ) {
			return this.pause().cycle();
		}

		return this.slide( pos > activeIndex ? 'next' : 'prev', $( this.$items[ pos ]) );
	};

	Carousel.prototype.pause = function ( e ) {
		if ( !e ) {
			this.paused = true;
		}

		if ( this.$element.find( '.vc_right.vc_carousel-control, .vc_left.vc_carousel-control' ).length && $.support.transition.end ) {
			this.$element.trigger( $.support.transition.end );
			this.cycle( true );
		}

		this.interval = clearInterval( this.interval );

		return this;
	};

	Carousel.prototype.next = function () {
		if ( this.sliding ) {
			return;
		}
		return this.slide( 'next' );
	};

	Carousel.prototype.prev = function () {
		if ( this.sliding ) {
			return;
		}
		return this.slide( 'prev' );
	};

	Carousel.prototype.slide = function ( type, next ) {
		var $active = this.$element.find( '.vc_item.vc_active' );
		var $next = next || $active[ type ]();
		var isCycling = this.interval;
		var direction = 'next' === type ? 'vc_left' : 'vc_right';
		var fallback = 'next' === type ? 'first' : 'last';
		var that = this;
		if ( !$next.length ) {
			if ( !this.options.wrap ) {
				this.returnSwipedSlide();
				return;
			}
			$next = this.$element.find( '.vc_item' )[ fallback ]();
		}

		this.sliding = true;

		if ( isCycling ) {
			this.pause();
		}

		var e = $.Event( 'slide.vc.vcCarousel', { relatedTarget: $next[ 0 ], direction: direction });

		if ( $next.hasClass( 'vc_active' ) ) {
			return;
		}

		if ( this.$indicators.length ) {
			this.$indicators.find( '.vc_active' ).removeClass( 'vc_active' );
			this.$indicators.find( '.vc_partial' ).removeClass( 'vc_partial' );
			this.$element.one( 'slid', function () {
				var index = that.getActiveIndex(),
					$nextIndicator = $( that.$indicators.children().slice( index,
						that.getActiveIndex() + that.options.perView ) );
				if ( $nextIndicator ) {
					$nextIndicator.addClass( 'vc_active' );
				}
				if ( that.options.partial && $nextIndicator ) {
					if ( index + 1 < that.items_count ) {
						$nextIndicator.last().next().addClass( 'vc_partial' );
					} else {
						$nextIndicator.first().prev().addClass( 'vc_partial' );
					}
				}
				if ( !that.options.wrap ) {
					that.showHideControl( index );
				}
			});
		}
		this.current_index = $next.index();

		if ( !that.options.wrap ) {
			this.showHideControl( this.current_index );
		}
		if ( this.current_index > this.items_count ) {
			this.current_index = 0;
		} else if ( 0 > this.current_index ) {
			this.current_index = this.items_count - 1;
		}
		if ( this.options.autoHeight ) {
			this.current_pos_value = - 1 * this._step * this.current_index;
		} else {
			this.current_pos_value = - 1 * $next.position()[ this.animation_position ];
		}
		if ( this.options.partial && this.current_index >= this.items_count - 1 ) {
			this.current_pos_value += this._step * ( 1 - this.partial_part );
		}
		if ( $.support.transition && this.$element.hasClass( 'vc_slide' ) ) {
			this.$element.trigger( e );
			if ( e.isDefaultPrevented() ) {
				return;
			}
			this.$slideline_inner
				.addClass( 'vc_transition' )
				.css( this.animation_position, this.current_pos_value + that.pos_units );
			if ( !this.options.autoHeight ) {
				this.recalculateSlidelineHeight( $next.height(), true );
			}
			this.$slideline_inner.one( $.support.transition.end, function () {
				$next.addClass( 'vc_active' );
				$active.removeClass( 'vc_active' );
				that.$slideline_inner.removeClass([
					type,
					'vc_transition'
				].join( ' ' ) );
				that.sliding = false;
				that.removeSwipeAnimationSpeed();
				setTimeout( function () {
					that.$element.trigger( 'slid' );
				}, 0 );
			}).emulateTransitionEnd( this.transition_speed );
		} else {
			this.$element.trigger( e );
			if ( e.isDefaultPrevented() ) {
				return;
			}
			$active.removeClass( 'vc_active' );
			$next.addClass( 'vc_active' );
			this.sliding = false;
			this.$slideline_inner.css( this.animation_position, this.current_pos_value + that.pos_units );
		}
		if ( isCycling ) {
			this.cycle();
		}

		return this;
	};
	Carousel.prototype.setSwipeAnimationSpeed = function () {
		this.$slideline_inner.addClass( 'vc_swipe-transition' );
	};
	Carousel.prototype.removeSwipeAnimationSpeed = function () {
		this.$slideline_inner.removeClass( 'vc_swipe-transition' );

	};
	/**
	 * Velocity
	 * @param   {Number}    delta_time
	 * @param   {Number}    delta_x
	 * @param   {Number}    delta_y
	 * @returns {Object}    velocity
	 */
	Carousel.prototype.velocity = function ( time, x ) {
		return {
			x: Math.abs( x / time ) || 0
		};
	};
	Carousel.prototype.recalculateSlidelineHeight = function ( height, animate ) {
		if ( true === animate ) {
			this.$slideline.animate({ height: height });
		} else {
			this.$slideline.height( height );
		}
	};
	/**
	 * Change layout size after resizing of window.
	 */
	Carousel.prototype.resizeAction = function () {
		var max_height = 0,
			new_slideline_height = 0;
		if ( 'horizontal' === this.options.mode ) {
			this.el_effect_size = this.$element.width() * ( this.options.partial ? this.partial_part : 1 );
			this.$slideline.width( this.items_count * this.el_effect_size );
		}

		if ( this.options.autoHeight ) {
			this.$items.height( 'auto' );
			this.$items.each( function () {
				var item_height = $( this ).height();
				if ( item_height > max_height ) {
					max_height = item_height;
				}
			});
			this.$items.height( max_height );
		} else {
			this.recalculateSlidelineHeight( this.$active.height() );
		}
		if ( 'vertical' === this.options.mode ) {
			this._step = this.$active.height();
			new_slideline_height = this.$active.height() * this.options.perView * ( this.options.partial ? ( 1 + 1 - this.partial_part ) : 1 );
			this.recalculateSlidelineHeight( new_slideline_height, false );
			this.$slideline_inner.css({ top: - 1 * this.$active.position().top });
			this.el_effect_size = this._step;
		}
	};
	Carousel.prototype.returnSwipedSlide = function () {
		var params = {};
		params[ this.animation_position ] = this.current_pos_value + this.pos_units;
		this.$slideline_inner.animate( params );
	};
	Carousel.prototype._build = function () {
		var el = this.$element.get( 0 ),
			_touch_start_position = false,
			_touch_start_time = 0,
			_pos_before_touch = 0,
			_diff = 0,
			_moved = false,
			that = this,
			mode = this.options.mode;
		this.getActiveIndex();

		this.el_width = 0;
		this.items_count = this.$items.length;

		this.$slideline = this.$element.find( '.vc_carousel-slideline' );
		this.$slideline_inner = this.$slideline.find( '> div' );
		this.slideline_inner = this.$slideline_inner.get( 0 );

		this.partial_part = 0.8;
		this._slide_width = 0;
		this.swipe_velocity = 0.7;
		this.current_pos_value = 0;
		this.current_index = 0; // TODO: default start position by options
		this.el_effect_size = 0;
		this.transition_speed = 600;

		this.$left_control = this.$element.find( '.vc_left.vc_carousel-control' );
		this.$right_control = this.$element.find( '.vc_right.vc_carousel-control' );

		// Enable autoHeight if partial
		if ( this.options.partial ) {
			this.options.autoHeight = true;
		}
		// Add Css classes for perView > 1
		if ( 1 < this.options.perView ) {
			this.$element.addClass( 'vc_per-view-more vc_per-view-' + this.options.perView );
		}

		if ( 'horizontal' === mode ) {
			this.pos_units = '%';
			this._step = 100.00 / this.items_count / this.options.perView;
			this.animation_position = 'left';
			this.$items.width( this._step + this.pos_units );
			this.touch_direction = 'pageX';
		} else {
			this.pos_units = 'px';
			this.animation_position = 'top';
			this.touch_direction = 'pageY';
			this.$element.addClass( 'vc_carousel_vertical' );
		}
		// Hide first control if this.current_index === 0
		if ( !that.options.wrap ) {
			this.showHideControl();
		}
		// Add partial css class if partial
		if ( this.options.partial ) {
			this.$element.addClass( 'vc_partial' );
		}
		// Set indicator
		if ( this.$indicators.length ) {
			var $active_indecators = that.$indicators.children()
				.slice( this.current_index, this.current_index + this.options.perView )
				.addClass( 'vc_active' );
			if ( this.options.partial ) {
				$active_indecators.last().next().addClass( 'vc_partial' );
			}
		}
		$( window ).resize( this.resizeAction.bind( this ) );
		this.resizeAction();

		el.addEventListener( 'touchstart', function ( e ) {
			_touch_start_position = parseFloat( e[ that.touch_direction ]);
			_touch_start_time = e.timeStamp;
			_pos_before_touch = that.$slideline_inner.position()[ that.animation_position ];
		}.bind( this ), false );
		el.addEventListener( 'touchmove', function ( e ) {
			_diff = parseFloat( e[ that.touch_direction ]) - _touch_start_position;
			_moved = 0 < Math.abs( _diff );
			if ( !_moved ) {
				return true;
			}
			e.preventDefault();
			that.slideline_inner.style[ that.animation_position ] = ( _pos_before_touch + _diff ) + 'px';
		}, false );
		el.addEventListener( 'touchend', function ( e ) {
			var time, part, velocity;
			if ( _moved ) {
				time = ( e.timeStamp - _touch_start_time ) / 1000;
				part = _diff / that.el_effect_size;
				velocity = that.velocity( time, part );
				if ( ( velocity.x > that.swipe_velocity && 0 > part ) || part <= - 0.7 ) {
					that.setSwipeAnimationSpeed();
					that.next();
				} else if ( velocity.x > that.swipe_velocity || 0.7 <= part ) {
					that.setSwipeAnimationSpeed();
					that.prev();
				} else {
					that.returnSwipedSlide();
				}
				_moved = false;
			}
		}, false );
		this.$element.addClass( 'vc_build' );

		return this;
	};
	// CAROUSEL PLUGIN DEFINITION
	// ==========================

	var old = $.fn.vcCarousel;

	$.fn.vcCarousel = function ( option, value ) {
		return this.each( function () {
			var $this = $( this );
			var data = $this.data( 'vc.vcCarousel' );
			var options = $.extend({}, Carousel.DEFAULTS, $this.data(), 'object' === typeof ( option ) && option );
			var action = 'string' === typeof ( option ) ? option : options.slide;

			if ( !data ) {
				data = new Carousel( this, options );
				$this.data( 'vc.vcCarousel', data );
			}
			if ( 'number' === typeof ( option ) ) {
				data.to( option );
			} else if ( action ) {
				data[ action ]( value );
			} else if ( options.interval ) {
				data.pause().cycle();
			}
		});
	};

	$.fn.vcCarousel.Constructor = Carousel;

	// CAROUSEL NO CONFLICT
	// ====================

	$.fn.vcCarousel.noConflict = function () {
		$.fn.vcCarousel = old;
		return this;
	};

	// CAROUSEL DATA-API
	// =================

	$( document ).off( 'click.vc.vcCarousel.data-api' ).on( 'click.vc.vcCarousel.data-api',
		'[data-slide], [data-slide-to]',
		function ( e ) {
			var $this = $( this ), href;
			var $target = $( $this.attr( 'data-target' ) || ( href = $this.attr( 'href' ) ) && href.replace( /.*(?=#[^\s]+$)/,
				'' ) ); // strip for ie7
			var options = $.extend({}, $target.data(), $this.data() );
			var slideIndex = $this.attr( 'data-slide-to' );
			if ( slideIndex ) {
				options.interval = false;
			}
			$target.vcCarousel( options );

			if ( slideIndex ) {
				$target.data( 'vc.vcCarousel' ).to( slideIndex );
			}

			e.preventDefault();
		});

	$( window ).on( 'load', function () {
		$( '[data-ride="vc_carousel"]' ).each( function () {
			var $carousel = $( this );
			$carousel.vcCarousel( $carousel.data() );
		});
	});
})( window.jQuery );
