/*
* jQuery-1.4.4 thumbnailGallery by FirstView (http://firstviewmedia.com).
* This lets you 
* Options include.
*/
/*
Eg. :


*/

(function($){
	$.fn.thumbsGallery = function(opts) {
	
		var defaults = {
			animating : true,						// Use fading, sliding or hard cut. //
			extraSpace : true,						// Centre images on ends. //
			
			bigSlideSpeed : 700,					// Duration of big image slding. //
			bigSlideEasing : 'easeInOutQuint',		// Easing of big image slding. //
			
			thumbSlideSpeed : 400,					// Duration of thumbnail image slding. //
			thumbSlideEasing : 'easeInOutQuint',	// Easing of thumbnail image slding. //
			
			thumbHoverOpacity : .5,					// Opacity of thumbnail when hovering over it. Initial opacity is set by css. //
			thumbHoverSpeed : 300,					// Duration of thumbnail hover animation. //
			thumbHoverEasing : 'easeInOutQuad',		// Easing of thumbnail image slding. //
			
			bigFadeOpacity : .2,					// Opacity of big images when it's not in view. //
			bigFadeSpeed : 400,						// Duration of big image hover animation. //
			bigFadeEasing : 'easeInOutQuint',		// Easing of big image hover. //
			
			infoSlideSpeed : 300,					// Duration of info div image slding. //
			infoSlideEasing : 'easeInOutCirc',		// Easing of info div image slding. //
			
			minDraggerWidth : 200,					// Minimum dragger width. //
			maxDraggerWidth : 600,					// Maximum dragger width. //
			
			youTubeSupport : true					// Supports youtube videos in the gallery. //
		};
		var opts								= $.extend(defaults, opts);
		var supportsOpacity						= $.support.opacity;
		
		return this.each(function(){
			
			
/*==================== DEFINE VARS ====================*/


			var $this							= $(this);
			var $nextBtn						= $this.find('.navigation.next');
			var $prevBtn						= $this.find('.navigation.previous');
			var $dragger						= $this.find('.scrollHandle');
			var $scrollbar						= $this.find('.thumbScrollBar');
			var $mainCont						= $this.find('.galleryContainer');
			var $thumbsCont						= $this.find('.galleryThumbViewport');
			var $thumbsSlider					= $this.find('.galleryThumbWrapper');
			var $thumb							= $this.find('.galleryThumbWrapper a');
			var $thumbImg						= $this.find('.galleryThumbWrapper a img');
			var $bigCont						= $this.find('.galleryViewport');
			var $bigSlider						= $this.find('.galleryImageContainerWrapper');
			var $big							= $this.find('.galleryImageContainerWrapper .galleryImageContainer');
			var $bigImg							= $this.find('.galleryImageContainerWrapper .galleryImageContainer img');
			var $imageInfo						= $this.find('.galleryItemHeader');
			var $loading						= $this.find('.galleryLoading');
			var $imageFilter					= $this.find('.galleryContainer .toggleView.pictures');
			var $videoFilter					= $this.find('.galleryContainer .toggleView.videos');
			var $allVideos						= $this.find('._jsGalleryFilterVideo');
			var $allImages						= $this.find('._jsGalleryFilterImage');
			
			var currentImgNum					= 0;
			var totalImgNum						= 0;
			var percLeft						= 0;
			var maxThumbsSliderLeft				= 0;
			var maxScrollbarLeft				= 0;
			var draggerWidth					= 0;
			var currentImgNum					= 0;
			
			var origThumbOpacity				= $thumb.css('opacity');
			var origImageInfoBottom				= $imageInfo.css('bottom');
			
			// Call Initial functions. //
			
			getTotalImgNum();
			resizeThumbsSlider();
			resizeBigSlider();
			resizeDragger();
			calcMaxScrollbarLeft();
			calcMaxThumbsSliderLeft();
			//hidePrevBtn();
			showImg(0);
			bindThumbs();
			bindBigImages();
			
			
/*==================== BINDING FUNCTIONS ====================*/
			
			
			// Add unique numbers for each thumbnail & hover and click. //
			function bindThumbs(){
				$thumb.unbind().filter(':visible').each(function( i ){
					$(this).data('imgNum', i)
					.hover(function(){
						if( supportsOpacity ){
							if( opts.animating ) $(this).stop(true, true).fadeTo(opts.thumbHoverSpeed, opts.thumbHoverOpacity, opts.thumbHoverEasing );
							else $(this).stop(true, true).fadeTo(1, opts.thumbHoverOpacity);
						}else $(this).css({'filter':'alpha(opacity='+opts.thumbHoverOpacity*100+')'});
					},function(){
						if( supportsOpacity ){
							if( opts.animating ) $(this).fadeTo(opts.thumbHoverSpeed, origThumbOpacity, opts.thumbHoverEasing );
							else $(this).fadeTo(1, origThumbOpacity);
						}else $(this).css({'filter':'alpha(opacity='+origThumbOpacity*100+')'});
					})
					.click(function( e ){
						e.preventDefault();
						showImg(i);
					});
				});
			}
			
			
			// Add unique numbers for each big image & click. //
			function bindBigImages(){
				$big.unbind().filter(':visible').each(function( i ){
					$(this).relToData().data('imgNum', i)
					.click(function( e ){
						e.preventDefault();
						if( i == currentImgNum && !$(this).data('youTubeId') ) showImg(i+1);
						//else showImg(i);
					});
				});
			}
			
			
			// For Webkit, which only gets image sizes when image finishes loading - resizes stuff. //
			$bigImg.load(function(){ resizeBigSlider(); });
			$thumbImg.load(function(){
				resizeThumbsSlider()
				resizeDragger();
				calcMaxScrollbarLeft();
				calcMaxThumbsSliderLeft();
			});
			
			
			// Next & Previous button clicks show next & previous images. //
			$nextBtn.click(function( e ){
				e.preventDefault();
				showNextImg();
			});
			$prevBtn.click(function( e ){
				e.preventDefault();
				showPrevImg();
			});
			
			
			// Show & hide Info container. //
			$mainCont.hover(function(){
				if( opts.animating ) $imageInfo.stop(true, true).animate({'bottom':0}, {duration:opts.infoSlideSpeed, easing:opts.infoSlideEasing});
				else $imageInfo.css({'bottom':0});
			},function(){
				if( opts.animating ) $imageInfo.animate({'bottom':origImageInfoBottom}, {duration:opts.infoSlideSpeed, easing:opts.infoSlideEasing});
				else $imageInfo.css({'bottom':origImageInfoBottom});
			});
			
			
			// Mouse wheeling for thumbnails - same as dragging. If there isn't a scrollbar scroll the page normally. //
			$thumbsCont.mousewheel(function(event, delta) {
				var draggerXPos			= $dragger.css('left').replace('px','');
				delta					*= 3;
				var newDraggerXPos		= draggerXPos-delta;
				
				if( newDraggerXPos >= maxScrollbarLeft ) newDraggerXPos = maxScrollbarLeft;
				else if( newDraggerXPos <= 0 ) newDraggerXPos = 0;
				if( delta > 0 ) $dragger.css({'left':newDraggerXPos});
				else if( delta < 0 ) $dragger.css({'left':newDraggerXPos});
				
				percLeft = maxScrollbarLeft/$dragger.css('left').replace('px','');
				posThumbsSlider(false);
				if( $thumbsCont.outerWidth(true) <= $thumbsSlider.outerWidth(true) ) return false;
				else return true;
			});
			
			
			// Dragger dragging. //
			$dragger.mousedown(function( e ){
				var mousedownXPos = e.pageX - $dragger.offset().left;
				$dragger
					.data('mousedown', true)
					.data('mousedownXPos', mousedownXPos)
					.addClass('active');
			});
			$('html').mousemove(function( e ){
				var bgMouseMoveXPos = e.pageX - $scrollbar.offset().left;
				if( $dragger.data('mousedown') ){
					var draggerXPos = bgMouseMoveXPos - $dragger.data('mousedownXPos');
					if( draggerXPos >= maxScrollbarLeft ) draggerXPos = maxScrollbarLeft;
					else if( draggerXPos <= 0 ) draggerXPos = 0;
					
					percLeft = maxScrollbarLeft/draggerXPos;
					$dragger.css({'left':draggerXPos});
					posThumbsSlider(false);
				}
			}).mouseup(function(){
				$dragger
					.data('mousedown', false)
					.data('mousedownXPos', 0)
					.removeClass('active');
			
			
			// Keyboard keys for next and previous images. //
			}).keydown( function ( event ) {
				if( event.keyCode == '39' ) showNextImg();
				else if( event.keyCode == '37' ) showPrevImg();
			});
			
			
			// Show Videos or images or both. //
			$imageFilter.click(function( e ){
				e.preventDefault();
				if( $imageFilter.data('selected') ){
					filterGallery();
					$imageFilter.data('selected', false).removeClass('selected');
				}else{
					filterGallery('images');
					$imageFilter.data('selected', true).addClass('selected');
					$videoFilter.data('selected', false).removeClass('selected');
				}
			});
			$videoFilter.click(function( e ){
				e.preventDefault();
				if( $videoFilter.data('selected') ){
					filterGallery();
					$videoFilter.data('selected', false).removeClass('selected');
				}else{
					filterGallery('videos');
					$videoFilter.data('selected', true).addClass('selected');
					$imageFilter.data('selected', false).removeClass('selected');
				}
			});

			
/*==================== FUNCTIONS TO PERFROM ====================*/

			
			// Show next & previous images. //
			function showNextImg(){ showImg( currentImgNum+1 ); }
			function showPrevImg(){ showImg( currentImgNum-1 ); }
			
			
			// The main show image function. //
			function showImg( imgNum ){
				
				// Conditionals. //
				if( imgNum <= 0 ){
					currentImgNum = 0;
					showNextBtn();
					hidePrevBtn();
				}else if( imgNum >= totalImgNum ){
					currentImgNum = totalImgNum;
					showPrevBtn();
					hideNextBtn();
				}else{
					currentImgNum = imgNum;
					showNextBtn();
					showPrevBtn();
				}
				
				if( imgNum < 0 ) return;
				else if( imgNum > totalImgNum ) return;
				
				// Left percentage calculation. //
				if( currentImgNum < totalImgNum*.5 ) var thumbsSliderLeft = $thumb.filter(':visible').eq(currentImgNum).data('scrollXPos');
				else var thumbsSliderLeft = $thumb.filter(':visible').eq(currentImgNum).data('scrollXPosAfter');
				percLeft = $thumbsSlider.outerWidth(true) / thumbsSliderLeft;
				
				// Change left values and image info. //
				changeImageInfo(currentImgNum);
				posBigSlider(currentImgNum);
				if( $thumbsCont.outerWidth(true) <= $thumbsSlider.outerWidth(true) ) posThumbsSlider(true);
				posDragger();
			}
			
			
			// Change the image information. //
			function changeImageInfo( imgNum ){
				/*
				Data needed in rel tag to work:
				imgData = {
					heading:''
					href:''
					description:''
					tags = [{
						title:''
						href:''
						class:''
						text:''
					}]
				}
				*/
				var imgData = $big.eq(imgNum).data();
				if( supportsOpacity && opts.animating ){
					$imageInfo.children().fadeOut(200,function(){ changeInfo(); });
				}else changeInfo();
				
				function changeInfo(){
					
					if( imgData.heading != null ){
						if( imgData.heading.toLowerCase() == 'title' ) imgData.heading = '';
					}else imgData.heading = '';
					$imageInfo.find('h2').html(imgData.heading);
					$imageInfo.find('.headerReadArticle').attr('href',imgData.href);
					$imageInfo.find('p').html(imgData.description);
					
					if(!imgData.href) $imageInfo.find('.headerReadArticle').hide();
					else $imageInfo.find('.headerReadArticle').show();
					if(!imgData.tags || !imgData.tags.length) $imageInfo.find('.tagBar').hide();
					else $imageInfo.find('.tagBar').show();
					if(!imgData.heading) $imageInfo.find('h2').hide();
					else $imageInfo.find('h2').show();
					
					var tagHtml = '';
					if( imgData.tags && imgData.tags.length){
						for(i=0;i<imgData.tags.length;i++){
							var comma = '';
							if( i+1 != imgData.tags.length ) comma = ', ';
							tagHtml += '<li><a class="'+imgData.tags[i].className+'" href="'+imgData.tags[i].href+'" title="'+imgData.tags[i].title+'">'+imgData.tags[i].text+'</a>'+comma+'</li>';
						}
					}
					$imageInfo.find('.tagBar ul').html(tagHtml);
					if( supportsOpacity && opts.animating ) $imageInfo.children().fadeIn(200);
				}
			}
			
			
			// Hide & show next and previous buttons. //
			function hideNextBtn(){
				if( supportsOpacity && opts.animating ) $nextBtn.fadeOut(300);
				else $nextBtn.hide();
			}
			function hidePrevBtn(){
				if( supportsOpacity && opts.animating ) $prevBtn.fadeOut(300);
				else $prevBtn.hide();
			}
			function showNextBtn(){
				if( $big.filter(':visible').size() <= 1 ){
					if( supportsOpacity && opts.animating ) $nextBtn.fadeOut(300);
					else $nextBtn.hide();
					return false;
				}
				if( supportsOpacity && opts.animating ) $nextBtn.fadeIn(300);
				else $nextBtn.show();
			}
			function showPrevBtn(){
				if( $big.filter(':visible').size() <= 1 ){
					if( supportsOpacity && opts.animating ) $prevBtn.fadeIn(300);
					else $prevBtn.hide();
					return false;
				}
				if( supportsOpacity && opts.animating ) $prevBtn.fadeIn(300);
				else $prevBtn.show();
			}
			
			
			// Position thumbnails. //
			function posThumbsSlider( animate ){
				var scrollXPos = -maxThumbsSliderLeft/percLeft;
				if( opts.animating && animate ) $thumbsSlider.animate({'left':scrollXPos},{duration:opts.thumbSlideSpeed, easing:opts.thumbSlideEasing});
				else $thumbsSlider.css({'left':scrollXPos});
			}
			
			
			// Position big images. //
			function posBigSlider( imgNum ){
				var scrollXPos = -$big.filter(':visible').eq(imgNum).data('scrollXPos');
				if( supportsOpacity ){
					if( opts.animating ){
						$big.filter(':visible').fadeTo(opts.bigFadeSpeed, opts.bigFadeOpacity, opts.bigFadeEasing);
						$big.filter(':visible').eq(imgNum).stop().fadeTo(opts.bigFadeSpeed, 1, opts.bigFadeEasing);
					}else{
						$big.filter(':visible').fadeTo(1, opts.bigFadeOpacity);
						$big.filter(':visible').eq(imgNum).stop().fadeTo(1, 1);
					}
				}else{
					$big.filter(':visible').css({'filter':'alpha(opacity='+opts.bigFadeOpacity*100+')'});
					$big.filter(':visible').eq(imgNum).css({'filter':'alpha(opacity='+100+')'});
				}
				if( opts.animating ){
					$bigSlider.animate({'left':scrollXPos},
						{duration:opts.bigSlideSpeed,
						easing:opts.bigSlideEasing,
						complete:function(){changeYouTubeImages();}});
				}else{
					$bigSlider.css({'left':scrollXPos});
					changeYouTubeImages();
				}
				
				
				// Get youtube images and replace current videos with flash. //
				function changeYouTubeImages(){
					if( opts.youTubeSupport ){
						$big.filter(':visible').each(function(){
							if( $(this).data('youTubeId') ){
								var nextVidId	= $big.filter(':visible').eq(imgNum).data('youTubeId');
								var vidId		= $(this).data('youTubeId');
								
								if( vidId == nextVidId ){
									if( !$big.filter(':visible').eq(imgNum).find('.flashContainer').size() ){
										$big.filter(':visible').eq(imgNum).youTubeEmbed({video:'http://www.youtube.com/watch?v='+vidId,overwrite:true, width:550, height:390});
									}
								}else $(this).html('<img src="http://img.youtube.com/vi/'+vidId+'/0.jpg" alt="YouTube Video" />');
							}
						});
						resizeBigSlider();
					}
				}
			}
			
			
			// Position the dragger. //
			function posDragger(){
				var scrollXPos = maxScrollbarLeft/percLeft;
				if( opts.animating ) $dragger.animate({'left':scrollXPos},{duration:opts.thumbSlideSpeed, easing:opts.thumbSlideEasing});
				else $dragger.css({'left':scrollXPos});
			}
			
			
			// Show Videos, images or both. //
			function filterGallery( type ){
				if( type == 'videos' ){
					 $allVideos.show();
					 $allImages.hide();
				}else if ( type == 'images'){
					$allImages.show();
					$allVideos.hide();
				}else{
					 $allVideos.show();
					 $allImages.show();
				}
				
				
				// Basically recalculate gallery. //
				getTotalImgNum();
				resizeThumbsSlider();
				resizeBigSlider();
				resizeDragger();
				calcMaxScrollbarLeft();
				calcMaxThumbsSliderLeft();
				bindThumbs();
				bindBigImages();
				
				
				// Change opt.animating to hit straight back without any minor display changes. //
				var origOptsAnimating	= opts.animating;
				opts.animating			= false;
				showImg(0);
				opts.animating			= origOptsAnimating;
			}
			

/*==================== CALCULATION FUNCTIONS ====================*/

			
			// Calculate visible number of images. //
			function getTotalImgNum(){ totalImgNum = $thumb.filter(':visible').size()-1; }
			
			
			// Resize the thumbnail holder. //
			function resizeThumbsSlider(){
				var thumbsSliderWidth = 0;
				$thumb.filter(':visible').each(function( i ){
					$(this).data('scrollXPos', thumbsSliderWidth);
					thumbsSliderWidth += $(this).outerWidth(true)+0.25;
					$(this).data('scrollXPosAfter', thumbsSliderWidth);
				});
				
				
				// Put on an extra width, because it drops an image without it. //
				$thumbsSlider.width(thumbsSliderWidth);
				return thumbsSliderWidth;
			}
			
			
			// Resize the big images holder. //
			function resizeBigSlider(){
				var bigSliderWidth = 0;
				var extraSpace;
				$big.filter(':visible').each(function( i ){				
					// Give img extra space, or no space & store it for later. Add to bigSlider width. //
					if( !opts.extraSpace ){
						if( i>=totalImgNum ) extraSpace = $bigCont.outerWidth() - $(this).outerWidth(true);
						else if( i>0 ) extraSpace = ($bigCont.outerWidth() - $(this).outerWidth(true))*.5;
						else extraSpace = 0;
					}else extraSpace = ($bigCont.outerWidth() - $(this).outerWidth(true))*.5;
					$(this).data('scrollXPos', bigSliderWidth-extraSpace);
					bigSliderWidth += $(this).outerWidth(true);
				});
				$bigSlider.width(bigSliderWidth);
				return bigSliderWidth;
			}
			
			
			// Resize the dragger. //
			function resizeDragger(){
				
				
				// No need for a scrollbar. //
				if( $thumbsCont.outerWidth(true) >= $thumbsSlider.outerWidth(true) ){
					$scrollbar.hide();
					return;
				}
				
				
				// Conditionals. //
				var newDraggerWidth = $scrollbar.outerWidth(true) * ( $thumbsCont.outerWidth(true)/$thumbsSlider.outerWidth(true) );
				if( newDraggerWidth <= opts.minDraggerWidth ) newDraggerWidth = opts.minDraggerWidth;
				else if( newDraggerWidth >= opts.maxDraggerWidth ) newDraggerWidth = opts.maxDraggerWidth;
				
				$dragger.width(newDraggerWidth);
				$scrollbar.show();
				return $dragger.outerWidth;
			}
			
			
			// Calculate maximums. //
			function calcMaxScrollbarLeft(){ maxScrollbarLeft = $scrollbar.outerWidth(true) - $dragger.outerWidth(true); }
			function calcMaxThumbsSliderLeft(){ maxThumbsSliderLeft = $thumbsSlider.outerWidth(true) - $thumbsCont.outerWidth(true); }
					
			return this;
		});
		
	};
})(jQuery);

