/**
 * jquery.gallery.js
 * http://www.codrops.com
 *
 * Copyright 2011, Pedro Botelho / Codrops
 * Free to use under the MIT license.
 *
 * Date: Mon Jan 30 2012
 */

(function( $, undefined ) {
	
	/*
	 * Gallery object.
	 */
	$.Gallery 				= function( options, element ) {
	
		this.$el	= $( element );
		this._init( options );
		
	};
	
	$.Gallery.defaults 		= {
		current		: 0,	// index of current item
		autoplay	: false,// slideshow on / off
		interval	: 2000  // time between transitions
    };
	
	$.Gallery.prototype 	= {
		_init 				: function( options ) {
			
			this.options 		= $.extend( true, {}, $.Gallery.defaults, options );
			
			// support for 3d / 2d transforms and transitions
			this.support3d		= Modernizr.csstransforms3d;
			this.support2d		= Modernizr.csstransforms;
			this.supportTrans	= Modernizr.csstransitions;
			
			this.$wrapper		= this.$el.find('.dg-wrapper');
			
			this.$items			= this.$wrapper.children();
			this.itemsCount		= this.$items.length;
			
			this.$nav			= this.$el.find('nav');
			this.$navPrev		= this.$nav.find('.dg-prev');
			this.$navNext		= this.$nav.find('.dg-next');
			
			// minimum of 3 items
			if( this.itemsCount < 3 ) {
					
				this.$nav.remove();
				return false;
			
			}	
			
			this.current		= this.options.current;
			
			this.isAnim			= false;
			
			this.$items.css({
				'opacity'	: 0,
				'visibility': 'hidden'
			});
			
			this._validate();
			
			this._layout();
			
			// load the events
			this._loadEvents();
			
			// slideshow
			if( this.options.autoplay ) {
			
				this._startSlideshow();
			
			}
			
		},
		_validate			: function() {
		
			if( this.options.current < 0 || this.options.current > this.itemsCount - 1 ) {
				
				this.current = 0;
			
			}	
		
		},
		_layout				: function() {
			
			// current, left and right items
			this._setItems();
			
			// current item is not changed
			// left and right one are rotated and translated
			var leftCSS, rightCSS, currentCSS;
			
			if( this.support3d && this.supportTrans ) {
			
				leftCSS 	= {
					'-webkit-transform'	: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
					'-moz-transform'	: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
					'-o-transform'		: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
					'-ms-transform'		: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
					'transform'			: 'translateX(-350px) translateZ(-200px) rotateY(45deg)'
				};
				
				rightCSS	= {
					'-webkit-transform'	: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
					'-moz-transform'	: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
					'-o-transform'		: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
					'-ms-transform'		: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
					'transform'			: 'translateX(350px) translateZ(-200px) rotateY(-45deg)'
				};
				
				leftCSS.opacity		= 1;
				leftCSS.visibility	= 'visible';
				rightCSS.opacity	= 1;
				rightCSS.visibility	= 'visible';
			
			}
			else if( this.support2d && this.supportTrans ) {
				
				leftCSS 	= {
					'-webkit-transform'	: 'translate(-350px) scale(0.8)',
					'-moz-transform'	: 'translate(-350px) scale(0.8)',
					'-o-transform'		: 'translate(-350px) scale(0.8)',
					'-ms-transform'		: 'translate(-350px) scale(0.8)',
					'transform'			: 'translate(-350px) scale(0.8)'
				};
				
				rightCSS	= {
					'-webkit-transform'	: 'translate(350px) scale(0.8)',
					'-moz-transform'	: 'translate(350px) scale(0.8)',
					'-o-transform'		: 'translate(350px) scale(0.8)',
					'-ms-transform'		: 'translate(350px) scale(0.8)',
					'transform'			: 'translate(350px) scale(0.8)'
				};
				
				currentCSS	= {
					'z-index'			: 999
				};
				
				leftCSS.opacity		= 1;
				leftCSS.visibility	= 'visible';
				rightCSS.opacity	= 1;
				rightCSS.visibility	= 'visible';
			
			}
			
			this.$leftItm.css( leftCSS || {} );
			this.$rightItm.css( rightCSS || {} );
			
			this.$currentItm.css( currentCSS || {} ).css({
				'opacity'	: 1,
				'visibility': 'visible'
			}).addClass('dg-center');
			
		},
		_setItems			: function() {
			
			//this.$items.removeClass('dg-center');
			
			this.$currentItm	= this.$items.eq( this.current );
			this.$leftItm		= ( this.current === 0 ) ? this.$items.eq( this.itemsCount - 1 ) : this.$items.eq( this.current - 1 );
			this.$rightItm		= ( this.current === this.itemsCount - 1 ) ? this.$items.eq( 0 ) : this.$items.eq( this.current + 1 );
			
			if( !this.support3d && this.support2d && this.supportTrans ) {
			
				this.$items.css( 'z-index', 1 );
				this.$currentItm.css( 'z-index', 999 );
			
			}
			
			// next & previous items
			if( this.itemsCount > 3 ) {
			
				// next item
				this.$nextItm		= ( this.$rightItm.index() === this.itemsCount - 1 ) ? this.$items.eq( 0 ) : this.$rightItm.next();
				this.$nextItm.css( this._getCoordinates('outright') );
				
				// previous item
				this.$prevItm		= ( this.$leftItm.index() === 0 ) ? this.$items.eq( this.itemsCount - 1 ) : this.$leftItm.prev();
				this.$prevItm.css( this._getCoordinates('outleft') );
			
			}
			
		},
		_loadEvents			: function() {
			
			var _self	= this;
			
			this.$navPrev.on( 'click.gallery', function( event ) {
				
				if( _self.options.autoplay ) {
				
					clearTimeout( _self.slideshow );
					_self.options.autoplay	= false;
				
				}
				
				_self._navigate('prev');
				return false;
				
			});
			
			this.$navNext.on( 'click.gallery', function( event ) {
				
				if( _self.options.autoplay ) {
				
					clearTimeout( _self.slideshow );
					_self.options.autoplay	= false;
				
				}
				
				_self._navigate('next');
				return false;
				
			});
			
			this.$wrapper.on( 'webkitTransitionEnd.gallery transitionend.gallery OTransitionEnd.gallery', function( event ) {
				
				_self.$currentItm.addClass('dg-center');
				_self.$items.removeClass('dg-transition');
				_self.isAnim	= false;
				
			});
			
		},
		_getCoordinates		: function( position ) {
			
			if( this.support3d && this.supportTrans ) {
			
				switch( position ) {
					case 'outleft':
						return {
							'-webkit-transform'	: 'translateX(-450px) translateZ(-300px) rotateY(45deg)',
							'-moz-transform'	: 'translateX(-450px) translateZ(-300px) rotateY(45deg)',
							'-o-transform'		: 'translateX(-450px) translateZ(-300px) rotateY(45deg)',
							'-ms-transform'		: 'translateX(-450px) translateZ(-300px) rotateY(45deg)',
							'transform'			: 'translateX(-450px) translateZ(-300px) rotateY(45deg)',
							'opacity'			: 0,
							'visibility'		: 'hidden'
						};
						break;
					case 'outright':
						return {
							'-webkit-transform'	: 'translateX(450px) translateZ(-300px) rotateY(-45deg)',
							'-moz-transform'	: 'translateX(450px) translateZ(-300px) rotateY(-45deg)',
							'-o-transform'		: 'translateX(450px) translateZ(-300px) rotateY(-45deg)',
							'-ms-transform'		: 'translateX(450px) translateZ(-300px) rotateY(-45deg)',
							'transform'			: 'translateX(450px) translateZ(-300px) rotateY(-45deg)',
							'opacity'			: 0,
							'visibility'		: 'hidden'
						};
						break;
					case 'left':
						return {
							'-webkit-transform'	: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
							'-moz-transform'	: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
							'-o-transform'		: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
							'-ms-transform'		: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
							'transform'			: 'translateX(-350px) translateZ(-200px) rotateY(45deg)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
					case 'right':
						return {
							'-webkit-transform'	: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
							'-moz-transform'	: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
							'-o-transform'		: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
							'-ms-transform'		: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
							'transform'			: 'translateX(350px) translateZ(-200px) rotateY(-45deg)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
					case 'center':
						return {
							'-webkit-transform'	: 'translateX(0px) translateZ(0px) rotateY(0deg)',
							'-moz-transform'	: 'translateX(0px) translateZ(0px) rotateY(0deg)',
							'-o-transform'		: 'translateX(0px) translateZ(0px) rotateY(0deg)',
							'-ms-transform'		: 'translateX(0px) translateZ(0px) rotateY(0deg)',
							'transform'			: 'translateX(0px) translateZ(0px) rotateY(0deg)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
				};
			
			}
			else if( this.support2d && this.supportTrans ) {
			
				switch( position ) {
					case 'outleft':
						return {
							'-webkit-transform'	: 'translate(-450px) scale(0.7)',
							'-moz-transform'	: 'translate(-450px) scale(0.7)',
							'-o-transform'		: 'translate(-450px) scale(0.7)',
							'-ms-transform'		: 'translate(-450px) scale(0.7)',
							'transform'			: 'translate(-450px) scale(0.7)',
							'opacity'			: 0,
							'visibility'		: 'hidden'
						};
						break;
					case 'outright':
						return {
							'-webkit-transform'	: 'translate(450px) scale(0.7)',
							'-moz-transform'	: 'translate(450px) scale(0.7)',
							'-o-transform'		: 'translate(450px) scale(0.7)',
							'-ms-transform'		: 'translate(450px) scale(0.7)',
							'transform'			: 'translate(450px) scale(0.7)',
							'opacity'			: 0,
							'visibility'		: 'hidden'
						};
						break;
					case 'left':
						return {
							'-webkit-transform'	: 'translate(-350px) scale(0.8)',
							'-moz-transform'	: 'translate(-350px) scale(0.8)',
							'-o-transform'		: 'translate(-350px) scale(0.8)',
							'-ms-transform'		: 'translate(-350px) scale(0.8)',
							'transform'			: 'translate(-350px) scale(0.8)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
					case 'right':
						return {
							'-webkit-transform'	: 'translate(350px) scale(0.8)',
							'-moz-transform'	: 'translate(350px) scale(0.8)',
							'-o-transform'		: 'translate(350px) scale(0.8)',
							'-ms-transform'		: 'translate(350px) scale(0.8)',
							'transform'			: 'translate(350px) scale(0.8)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
					case 'center':
						return {
							'-webkit-transform'	: 'translate(0px) scale(1)',
							'-moz-transform'	: 'translate(0px) scale(1)',
							'-o-transform'		: 'translate(0px) scale(1)',
							'-ms-transform'		: 'translate(0px) scale(1)',
							'transform'			: 'translate(0px) scale(1)',
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
				};
			
			}
			else {
			
				switch( position ) {
					case 'outleft'	: 
					case 'outright'	: 
					case 'left'		: 
					case 'right'	:
						return {
							'opacity'			: 0,
							'visibility'		: 'hidden'
						};
						break;
					case 'center'	:
						return {
							'opacity'			: 1,
							'visibility'		: 'visible'
						};
						break;
				};
			
			}
		
		},
		_navigate			: function( dir ) {
			
			if( this.supportTrans && this.isAnim )
				return false;
				
			this.isAnim	= true;
			
			switch( dir ) {
			
				case 'next' :
					
					this.current	= this.$rightItm.index();
					
					// current item moves left
					this.$currentItm.addClass('dg-transition').removeClass('current').css( this._getCoordinates('left') );
					
					// right item moves to the center
					this.$rightItm.addClass('dg-transition current').css( this._getCoordinates('center') );	
					
					// next item moves to the right
					if( this.$nextItm ) {
						
						// left item moves out
						this.$leftItm.addClass('dg-transition').css( this._getCoordinates('outleft') );
						
						this.$nextItm.addClass('dg-transition').css( this._getCoordinates('right') );
						
					}
					else {
					
						// left item moves right
						this.$leftItm.addClass('dg-transition').css( this._getCoordinates('right') );
					
					}
					break;
					
				case 'prev' :
				
					this.current	= this.$leftItm.index();
					
					// current item moves right
					this.$currentItm.addClass('dg-transition').removeClass('current').css( this._getCoordinates('right') );
					
					// left item moves to the center
					this.$leftItm.addClass('dg-transition current').css( this._getCoordinates('center') );
					
					// prev item moves to the left
					if( this.$prevItm ) {
						
						// right item moves out
						this.$rightItm.addClass('dg-transition').css( this._getCoordinates('outright') );
					
						this.$prevItm.addClass('dg-transition').css( this._getCoordinates('left') );
						
					}
					else {
					
						// right item moves left
						this.$rightItm.addClass('dg-transition').css( this._getCoordinates('left') );
					
					}
					break;	
					
			};
			
			this._setItems();
			
			if( !this.supportTrans )
				this.$currentItm.addClass('dg-center');
			
		},
		_startSlideshow		: function() {
		
			var _self	= this;
			
			this.slideshow	= setTimeout( function() {
				
				_self._navigate( 'next' );
				
				if( _self.options.autoplay ) {
				
					_self._startSlideshow();
				
				}
			
			}, this.options.interval );
		
		},
		destroy				: function() {
			
			this.$navPrev.off('.gallery');
			this.$navNext.off('.gallery');
			this.$wrapper.off('.gallery');
			
		}
	};
	
	var logError 			= function( message ) {
		if ( this.console ) {
			console.error( message );
		}
	};
	
	$.fn.gallery			= function( options ) {
	
		if ( typeof options === 'string' ) {
			
			var args = Array.prototype.slice.call( arguments, 1 );
			
			this.each(function() {
			
				var instance = $.data( this, 'gallery' );
				
				if ( !instance ) {
					logError( "cannot call methods on gallery prior to initialization; " +
					"attempted to call method '" + options + "'" );
					return;
				}
				
				if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
					logError( "no such method '" + options + "' for gallery instance" );
					return;
				}
				
				instance[ options ].apply( instance, args );
			
			});
		
		} 
		else {
		
			this.each(function() {
			
				var instance = $.data( this, 'gallery' );
				if ( !instance ) {
					$.data( this, 'gallery', new $.Gallery( options, this ) );
				}
			});
		
		}
		
		return this;
		
	};
	
})( jQuery );