/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);

jQuery(document).ready(function($) { 
	// Bail if no images, not a slideshow, IE6 
	if($('.gallery-item').length === 0) {return;}
	if(!$('.gallery').hasClass('gallery-slideshow')) {return;}
	if($('body').hasClass('ie6')) {$('body').removeClass('js'); return;}
	
	var debug = false;
	
	// Helper functions
	function log(c){
		if(debug === true & 'undefinded' !== typeof console){
			console.log(c);
		}
	}	

	function mkA(i,c,t){
		return $('<a />',{'href':'#','id':i,'class':c,text:t});
	}
	
	function mkDIV(i,c,t){
		return $('<div />',{'id':i,'class':c});
	}
	
	function bool(a){
		return 'true' === a;
	}
	
	// Map WP plugin transition names to jQuery Cycle transition names
	var transitions = {
		'cross_fade': 'fade',
		'slide_left': 'scrollHorzCustom',
		'slide_vert': 'scrollVert'
	};
	
	var slideshowID = 1,
		slideshowWrapper = mkDIV(null,'slideshow-wrapper').css('position','relative').appendTo('body').css('visibility','hidden'),
		slideshow = mkDIV(null,'slideshow').appendTo(slideshowWrapper).css('visibility','hidden').hide(),
		gallery = $('.gallery').eq(0).hide(),
		galleryItems = gallery.find('.gallery-item'),
		sWidth = slideshowWrapper.width(),
		sHeight = slideshowWrapper.height(),
		caption = mkDIV(null,'slideshow-caption'),
		controls = mkDIV(null,'slideshow-controls'),
		pager = mkDIV(null,'slideshow-pager'),
		controlNext = mkA('slideshow-controls-next-'+slideshowID,'slideshow-controls-next','>').attr('title','next image').prependTo(controls),
		controlPause = mkA('slideshow-controls-pause-'+slideshowID,'slideshow-controls-pause','||').attr('title','pause or resume slideshow'),
		controlPrev = mkA('slideshow-controls-prev-'+slideshowID,'slideshow-controls-prev','<').attr('title','previous image').prependTo(controls),
		l = galleryItems.length,
		loading = $('<div id="slideshow-loading"><img class="loader" src="'+portfolialSlideshowOptions.loaderImage+'" /></div>').insertBefore(gallery),
		imageElements = [],
		imageSources = [],
		opt = {},
		slideshowPager,
		slideshowItemWidth,
		slideshowPagerWrapper,
		pagerOrientation = 'h',
		setup = false,
		newSlide = false,
		previousItem = null,
		cycleOptions = {};

	opt.transition = 'undefined' !== typeof transitions[portfolialSlideshowOptions.transition] ? transitions[portfolialSlideshowOptions.transition] : portfolialSlideshowOptions.transition;
	opt.holdTime = 'undefined' !== typeof portfolialSlideshowOptions.holdTime? +portfolialSlideshowOptions.holdTime : 3000;
	opt.fadeTime =  'undefined' !== typeof portfolialSlideshowOptions.fadeTime? +portfolialSlideshowOptions.fadeTime : 3000;
	opt.navigation = portfolialSlideshowOptions.navigation || null;
	opt.prevNext = bool(portfolialSlideshowOptions.showPrevNext);
	opt.automatic =  bool(portfolialSlideshowOptions.automatic);
	opt.centreImages = bool(portfolialSlideshowOptions.centreImages);
	opt.layout = portfolialSlideshowOptions.layout;
	opt.showMultiple = bool(portfolialSlideshowOptions.showMultiple);
	opt.groupWithNext = ("undefined" !== typeof portfolialSlideshowOptions.galleryGroups)? $.parseJSON(portfolialSlideshowOptions.galleryGroups.replace(/&quot;/g,'"')) : {};
	opt.debug = true;
	log(opt);
			
	slideshowClasses = [
		'slideshow-' + opt.layout,
		'slideshow-' + opt.navigation,
		'slideshow-' + (opt.prevNext? 'show-controls' : ''),
	];
		
	slideshowWrapper.addClass(slideshowClasses.join(' '));
		
	switch(opt.layout){
		case 'navigation_right':
		case 'navigation_left':
			sWidth = slideshow.width();
			pagerOrientation = 'v';
			break;	
	}
	
	// Custom scrollHorz transition
	$.fn.cycle.transitions.scrollHorzCustom = function($cont, $slides, opts) {
		$cont.css('overflow','hidden').width();
	
		opts.before.push(function(curr, next, opts, fwd) {
			$.fn.cycle.commonReset(curr,next,opts);	
			opts.cssBefore.left = fwd ? (sWidth-1) : (1-sWidth);
			opts.animOut.left = fwd ? -sWidth : sWidth;
	
		});
	
		opts.cssFirst = { left: 0 };
		opts.cssBefore= { top: 0 };
		opts.animIn   = { left: 0 };
		opts.animOut  = { top: 0 };
	};
    
    addImage(0);
    
	function addImage(i, add, opts, fwd){
		var src = galleryItems.eq(i).data('source'),
			group;
		imageElements[i] = new Image();
		
		//Resize each image to fit calling the next image once done
		imageElements[i].onload = function(){
			var image;
			
			image = resizeToFit.call(this, sWidth, sHeight, opt.centreImages);
			
			$(image).data('group',opt.groupWithNext[galleryItems.eq(i).data('postid')]);
			
			if(add) {
				// Could we put this in an onAddSlide callback?
				setup = false;

				var slide = afterItemLoaded(i, image);
				// add our next slide 
	            if(slide) {
	            	opts.addSlide(slide, fwd == false);
					updatePager('.slideshow-pager');
	            } else {
	            	// It's a double so skip this one
	            	onAddSlide(null);
	            } 
				return;
			}
			var slide = afterItemLoaded(i, image);
	        if(slide) {
	            //Add image to slideshow
				slideshow.append(slide);
            } 
            
			if(i<1) {		
				addImage(++i);
			} else {
				loadSlideshow();
			}
		}
		
		log('Add image '+i+' '+src);
			
		//Trigger the onload
		imageElements[i].src = src;
		if(add) {
			return imageElements[i];
		}
	};
	
	function afterItemLoaded(i, element) {	
		var width, height, wrap, image1, image2, item, pager, thumbs, paddingV, paddingH, postID;			
		item = $(element);
		item.data('originalIndex', i);	

		if(opt.showMultiple) {
			paddingV = 0;
			paddingH = 0;
				
			// The first image has nothing to compare with
			if(previousItem === null || group === "false") {
				previousItem = item;
				group = item.data('group') || "false";
				
				return group === "false" ? item : false;
			}
		
			width = +item.css('width').replace(/px/,'');
			height = +item.css('height').replace(/px/,'');

			previousWidth =  +previousItem.css('width').replace(/px/,'')
			log(width, previousWidth, width + previousWidth)

			// The two images are too wide so scale them down
			if( previousWidth + width > sWidth) {
				var ratio = (previousWidth + width) / sWidth;
				
				// Set the new widths
				width = Math.floor(width/ratio);
				previousWidth = Math.floor(previousWidth/ratio);
				
				item.css({'width': width, 'height': 'auto'});
				previousItem.css({'width': previousWidth, 'height': 'auto'});
				
				height = height / ratio;

			}	
			
			// The two items fit, so wrap them in a div and insert
			// them in place of the two items
			wrap = $('<div class="slideshow-double">').width(previousWidth + width);
			previousItem.after(wrap);
			
			previousItem.css('padding','0').appendTo(wrap);
			item.css('padding','0').appendTo(wrap);	
			
			// Add padding to centre the multiple image
			paddingH = (sWidth - (previousWidth + width)) / 2;			
			paddingV = (sHeight - height) / 2;
			wrap.css('padding', paddingV+'px '+paddingH+'px');
			
			// Skip the next item
			previousItem = null;

			return wrap;
		}
		
		return item
	}
	
	//Set-up the slideshow
	function loadSlideshow(){
		var pagerItemClass, pagerItem, slideshowClasses, pagerWidth, opts;
		
		log('initialize slideshow');	
		
		loading.remove();
		
		
		slideshow.hide().css('visibility','visible').fadeIn('slow');
		slideshowWrapper.prepend(slideshow).insertBefore(gallery).css('visibility','visible');
		addControls();
		
		//slideshow.children().each(afterItemLoaded);
		
		cycleOptions = slideshow.cycle({
			fx: opt.transition, 
			timeout: opt.holdTime,
			speed: opt.fadeTime,
			fastOnEvent: 500,
			containerResize: false,
			width: sWidth,
			height: sHeight,
			next: '#slideshow-controls-next-'+slideshowID,
			prev: '#slideshow-controls-prev-'+slideshowID,
			pager: '.slideshow-pager',
			pagerAnchorBuilder: buildPager,
			onPagerEvent: pagerScroll,
			onPrevNextEvent: prevNextScroll,
			onAddSlide: onAddSlide,
			updateActivePagerLink: updatePager,
			debug: opt.debug,
		}).data('cycle.opts');
		
		if(!opt.automatic) {slideshow.cycle('pause');}	
		
		// Two slides have already been added so Cycle won't 
		// choke. Now we trigger the rest of them
		onAddSlide();
			
	}
	
	function onAddSlide(slide){
		var nextIndex = imageElements.length;
		
		if(imageElements.length !== galleryItems.length) {
			log('load: '+ galleryItems.eq(nextIndex).data('source') )
			
			// on the first pass, addSlide is undefined (plugin hasn't yet created the fn yet) 
            if (!cycleOptions.addSlide) {
                return;
            }
            
            addImage(nextIndex, true, cycleOptions, true);  
       }
	}
	
	// We sneak in here to set up our fancy pager because there is no specific callback
	// available for "when the pager has been built".
	function updatePager(pagerSelector, startingSlide, activePagerClass){
		var lastSlideshowPagerItem;
		
		
		// We have already done our set up so call the default handler
		if(setup){
			$.fn.cycle.updateActivePagerLink(pagerSelector, startingSlide, activePagerClass);
			return true;
		}
		
		slideshowPager = $(pagerSelector);
		lastSlideshowPagerItem = slideshowPager.children().last();
		
		if(opt.layout === 'navigation_left' || opt.layout === 'navigation_right' ) {
			slideshowPager.css({height: slideshowPager.innerHeight()});		
		} else {
			slideshowPager.width('99999em');
			slideshowPager.css({
				width: lastSlideshowPagerItem.outerWidth(true) + lastSlideshowPagerItem.position().left, 
				height: lastSlideshowPagerItem.outerHeight(true)}
			)
		}
		
		slideshowPagerWrapper = $('.slideshow-pager-wrapper');
		
		if(slideshowPagerWrapper.length === 0) {
			slideshowPager.wrap('<div class="slideshow-pager-wrapper"></div>');
			slideshowPagerWrapper = $('.slideshow-pager-wrapper');
		}
		
		slideshowItemWidth = +slideshowPager.find('img').width();

		if( opt.layout === 'navigation_left' || opt.layout === 'navigation_right' ) {
			slideshowPager.height('auto');	
		}
		
		if('undefined' === typeof slideshowPager.data('pagerControlsBuilt') 
			&& (slideshowPager.width() > slideshowPagerWrapper.width() || slideshowPager.height() > slideshowPagerWrapper.height())
		) {
			slideshowPagerWrapper.before(pagerLink('prev', -4*slideshowItemWidth).hide()).before(pagerLink('next', 4*slideshowItemWidth));
			slideshowPager.data('pagerControlsBuilt', true).children().first().addClass('activeSlide');
		}
		
		setup = true;
	}
	
	
	// Callback for Cycle onPrevNextEvent
    function prevNextScroll(isNext, i, slideElement){
    	pagerScroll(i, slideElement);
    }
    
    // Callback for Cycle onPagerEvent
    // Scrolls the pager to reveal the next / prev items
	function pagerScroll(i, slideElement){		
		var currentPagerElement = slideshowPager.children().eq(i),
			offset = '+=0';
			transitionTime = 1000,
			orientation = (opt.layout === 'navigation_left' || opt.layout === 'navigation_right' )? 'v' : 'h',
			sizeLimit = orientation === 'v' ? sHeight : sWidth,
			pagerItemOffset = orientation === 'v' ? currentPagerElement.offset().top - slideshowPagerWrapper.offset().top: currentPagerElement.offset().left - slideshowPagerWrapper.offset().left,
			pagerItemSize = orientation === 'v' ? currentPagerElement.outerHeight(true) : currentPagerElement.outerWidth(true);
		
		if(pagerItemOffset < 0 || pagerItemOffset > sizeLimit){
			// If we have chosen an item that is not visible, scroll to it directly
			doPagerScroll(currentPagerElement);
			return;
		} else if(pagerItemOffset > (sizeLimit*0.70) || pagerItemOffset + pagerItemSize > (sizeLimit*0.70)) {
			offset = '+='+pagerItemSize+'px';
		} else if(pagerItemOffset < (sizeLimit*0.30) || pagerItemOffset + pagerItemSize < (sizeLimit*0.30)) {
			offset = '-='+pagerItemSize+'px'
		}
		
		doPagerScroll(orientation === 'v' ?  {top: offset, left: 0} : {top: 0, left: offset});
	}
	
	// Builds a prev / next link for the pager
	function pagerLink(dir, offset){
		// We need to conver the offset into a relative value string for scrollTo (eg -40 => '-=40px')
		offset = offset<0? String(offset).replace(/([\-])/,'$1=')+'px' : '+='+String(offset)+'px';			
	
		var pagelink = $('<a />', {
			text : dir === 'prev'? '<' : '>',
			'id' : 'slideshow-pager-'+dir,
			'class': 'slideshow-pager-'+dir+' slideshow-controls-'+dir,
			click: function(e) {
				e.preventDefault();
				doPagerScroll(pagerOrientation === 'v' ?  {top: offset, left: 0} : {top: 0, left: offset});
			}
		});
		
		return pagelink; 
	}
	
	function doPagerScroll(target){
		var transitionTime = 1000;

		slideshowPagerWrapper.stop().scrollTo(target, transitionTime, {onAfter: function(scrollTarget, opts){
			if((pagerOrientation === 'h' && slideshowPager.position().left === 0 ) || (pagerOrientation === 'v' && slideshowPager.position().top === 0) ) {
				$('#slideshow-pager-prev').hide();
			} else {
				$('#slideshow-pager-prev').show();
			}
			
			log(slideshowPagerWrapper.height() , slideshowPager.position().top + slideshowPager.height(), slideshowPager.children().length);
			
			if((pagerOrientation === 'h' && slideshowPagerWrapper.width() === slideshowPager.position().left + slideshowPager.width()) ||
				(pagerOrientation === 'v' && (slideshowPagerWrapper.height() === slideshowPager.position().top + slideshowPager.height() + slideshowPager.children().length))){
				$('#slideshow-pager-next').hide();
			} else {
				$('#slideshow-pager-next').show();
			}
			
		}});
	}

	function buildPager(i, el){
		var pagerItemClass = '',
			pagerItem = '',
			galleryElement = $(el);
			
		switch (opt.navigation){
			case "navigation_thumbnails_small":
			case "navigation_thumbnails_large":
				pagerItemClass = 'thumbnail';
				// This gallery element contains multiple images
				if(galleryElement.hasClass('slideshow-double')){
					pagerItem = ''
					// Append the original gallery element for each child element to the pager item 
					galleryElement.children().each(function(){
						pagerItem += gallery.find('a').eq($(this).data('originalIndex')).html();
					});
					pagerItemClass += ' double';
				} else {
					var galleryThumbnail = gallery.find('a').eq(galleryElement.data('originalIndex')).html();
					pagerItem = null !== galleryThumbnail ? galleryThumbnail : i+1 ;
				}
				
				break;
			case "navigation_numbers":
				pagerItem = i+1;
				pagerItemClass = 'number';
				break;
			case "navigation_dots":	
				pagerItemClass = 'dot';
				pagerItem ='<span>&#8226;</span>';
				break;
		}
	
		return mkA(null,pagerItemClass).html(pagerItem).get();	
	}
 	
	function addControls(){	
		slideshowWrapper.append(caption);
	
		switch(opt.layout){
			case 'navigation_top':
			case 'navigation_left':
				slideshowWrapper.prepend(pager);
				break;
			case 'navigation_right':
			case 'navigation_bottom':
				slideshowWrapper.append(pager);
				break;	
		}
		
		if(opt.prevNext) { 
			if(opt.automatic) {controlPrev.after(controlPause);}
			slideshowWrapper.append(controls);
		}
		
		controlPause.click(togglePause);
		slideshow.click(togglePause);
	}
	
	function togglePause(){
		var text = controlPause.text();
		switch(text){
			case '||':
				controls.addClass('slideshow-paused');
				slideshow.cycle('pause');
				controlPause.text('>');
				break;
			case '>':
				controls.removeClass('slideshow-paused');
				slideshow.cycle('resume').cycle('next');
				controlPause.text('||');
				break;
		}
		
		return false;
	}

	function resizeToFit(maxWidth,maxHeight,centre){
		var image = $(this),
			imageWidth = this.width,
			imageHeight = this.height,
			wScale = maxWidth / imageWidth,
			hScale = maxHeight / imageHeight,
			ratio = imageWidth / imageHeight,
			newTop = 0,
			paddingString = '', topMargin, html, hPadding = 0, vPadding = 0,
			newWidth,  newHeight;
		if(typeof centre === 'undefined') {centre = true;}
		
		newWidth = imageWidth;
		newHeight = imageHeight;
		
		//reset the image size to automatic
		image.width('auto').height('auto').css({width:'auto',height:'auto',padding:'0'});
	
		if(imageWidth>maxWidth){
			//downscale width;
			newWidth = maxWidth;
			newHeight = maxWidth/ratio;
		}
		
		// Once we have scaled the width we check
		// if the image is still too tall
		if(newHeight>maxHeight) {
			//downscale  height
			newHeight = maxHeight;
			newWidth = maxHeight*ratio;
		} 

		image.height(newHeight);
		image.width(newWidth);
		if(centre){
			//Padding to centre the image
			hPadding = Math.max(0,(maxWidth-newWidth)/2) + 'px';
			vPadding = Math.max(0,(maxHeight-newHeight)/2) + 'px';
			paddingString = vPadding+' '+hPadding;
			log(paddingString);
			image.css('padding',paddingString);
		}
		
		log('Resized image ' +this.src);	
		return image;
	}
});
