// base tile slide plugin
// @todo add viewport within a viewport to see (parts of) other slides?
// orientation of main
// div of viewport
// ul id with gallery 1
// ul id gallery 2
// id button up, down. left, right
// animation type
// speed
// callbacks:
// - onstart change main
//
// - onfinish change main

// Set scope for the lock
var lock = false;

/**
 * 7U TileSlide plugin for jQuery
 * 
 * Takes a ul with (optionally) nested ul's to make a clickable slider which scrolls
 * verticaly for the main UL and horizontaly for the sub-slides 
 * 
 * 
 * todo:
 * - option for choosing main orientation
 * - ? create a 'buffer' ( see slides up/down/left/right of the 'current' slide)
 * - done: triggers (onStartSlide, onEndSlide)
 * 
 * Slides should be a UL with LI's for the main nav
 * second nav are UL's again with LI's. There can be an img or html for content
 */
(function($)
{
	$.fn.tileSlide = function( options )
	{
		var defaults = {
			slides : 'slides',
			direction : 'vertical',
			nextSlide : 'nextSlide',
			prevSlide : 'prevSlide',
			nextSubSlide : 'nextSubSlide',
			prevSubSlide : 'prevSubSlide',
			loop : false,
			subloop : false,
			width : 300,
			height : 200,
			animationSpeed : 'slow',
			animationType : 'jswing',
			
			// callbacks for the buttons
			onNextSlideStart : function(){},
			onNextSlideEnd : function(){},
			onPrevSlideStart : function(){},
			onPrevSlideEnd : function(){},

			onNextSubSlideStart : function(){},
			onNextSubSlideEnd : function(){},
			onPrevSubSlideStart : function(){},
			onPrevSubSlideEnd : function(){},
			
			// Subslide hack
			prevSubSlidehack : false,
						
			iecommaforgetvar : null
		};
		
		var opts = $.extend( defaults, options );

		// ref to ul containing slides
		var slidesUL = $('#' + opts.slides );
//		var slidesLI = $('#' + opts.slides + ' li' );
//		var subslidesLI = $('#' + opts.slides + ' li ul li' );
		
		// to 'lock' clicks if an animation is busy
		lock = false;
		// holds current Slide jQuery object
		var currentSlide ;
		
		//////////////////////////////////////
		// Set 'current' slides
		//////////////////////////////////////				
		$('#' + opts.slides + ' > li:first' ).addClass('current-slide');
		
		currentSlide = $('#' + opts.slides + ' li:first' );
		 
		$('#' + opts.slides + ' > li:first > ul > li:first' ).addClass('current-subslide');

		// set css for upDown
		if( opts.direction == 'vertical' )
		{
			var slidesWidth = opts.width;
			var slidesHeight = $('#' + opts.slides + ' > li' ).length * opts.height;
			opts.subdirection = 'horizontal';
			// get slides and move it to viewport
			$(this).append( slidesUL );
		}
		else
		{
			var slidesWidth = $('#' + opts.slides + ' > li' ).length * opts.width;
			var slidesHeight = opts.height;
			opts.subdirection = 'vertical';
		}
		
		// Hide the prev / next slide buttons if there are less
		// than 5 projects
		if ( $('#'+opts.slides+' > li').length < 5 ) {
			$('#slide-up, #slide-down').hide();
		}

		
		//////////////////////////////////////
		// Set CSS
		//////////////////////////////////////
		
		// viewport
		$(this).css({
			width : opts.width + 'px', 
			height : opts.height + 'px',
			'background-color' : '#ccc',
			margin : '0px',
			padding : '0px'
		});
		
		// main UL
		slidesUL.css({
			margin : '0px',
			padding : '0px',
			position : 'absolute',
			left : '0px',
			top : '0px',
			width : slidesWidth + 'px',
			height : slidesHeight + 'px',
			listStyleType : 'none'
		});
		// main UL LI's	
		$('#' + opts.slides + ' > li').css({
			width : opts.width + 'px',	
			height : opts.height + 'px',
			margin : '0px',
			padding : '0px'
		});
		
		// Sub UL's
		$('#' + opts.slides + ' > li > ul').css({
			position : 'absolute',
			width: '10000px',
			height: opts.height + 'px',
			listStyleType : 'none',
			margin : '0px',
			padding : '0px'			
		});
		
				
		// Sub UL LI's
		$('#' + opts.slides + ' > li > ul > li' ).css({
			width : opts.width + 'px',
			height : opts.height + 'px',
			overflow : 'hidden',
			margin : '0px',
			padding : '0px',
			listStyleType : 'none',
			'float': 'left'
		});		
		
//		console.log( $('#slides').offset() );

		//////////////////////////////////////
		// Set listeners
		//////////////////////////////////////
		
		// setup click handlers (todo: make generic) 
		$('.' + opts.nextSlide ).click( function()
		{
//			console.log( $('#slides').offset() );
			if( opts.direction == 'vertical' )		
				var dir = 'up';
			else
				var dir = 'next';
			
			$('#viewport > #' + opts.slides + ' > li.current-slide > ul').css({left: "0"});
				 
			slide( 	'#viewport > #' + opts.slides , 
					'current-slide', 
					dir, 
					opts.loop, 
					1, 
					opts.onNextSlideStart, 
					function()
					{
						fixSubSlide( '#viewport > #' + opts.slides + ' > li.current-slide > ul > li:first' );
						//$('#' + opts.slides + ' > li > ul').css({ top: "0", left: "0"});
						return opts.onNextSlideStart;
					}
			);
					
			return false;
		});
		 
		$('.' + opts.prevSlide ).click( function()
		{			
			if( opts.direction == 'vertical' )		
				var dir = 'down';
			else
				var dir = 'prev';
			
			$('#viewport > #' + opts.slides + ' > li.current-slide > ul').css({left: "0"});
			
			slide( 	'#viewport > #' + opts.slides , 
					'current-slide', 
					dir, 
					opts.loop, 
					1, 
					opts.onPrevSlideStart, 
					function()
					{
						fixSubSlide( '#viewport > #' + opts.slides + ' > li.current-slide > ul > li:first' );
						return opts.onNextSlideStart;
					}
			);
					
			return false; 		
		});

		$('.' + opts.nextSubSlide ).click( function()
		{
			if( opts.direction == 'vertical' )		
				var dir = 'next';
			else
				var dir = 'up';
				
			slide( 	'#viewport > #' + opts.slides + ' > li.current-slide > ul', 
					'current-subslide', 
					dir, 
					opts.subloop, 
					1 ,
					opts.onNextSubSlideStart, 
					opts.onNextSubSlideEnd 					
					);
					
			return false;	
		});

		$('.' + opts.prevSubSlide ).click( function()
		{
			if( opts.direction == 'vertical' )
				var dir = 'prev';
			else
				var dir = 'down';
				
			slide( 	'#viewport > #' + opts.slides + ' > li.current-slide > ul', 
					'current-subslide', 
					dir,
					opts.subloop,
					1,
					opts.onPrevSubSlideStart, 
					opts.onPrevSubSlideEnd
					);
			
			return false;	
		});
		
		
		/**
		 * Return ?
		 */
		return this.each( function() {} );
		
		
		/**
		 * executes prev and next actions
		 *
		 * @param base 			selector path to class
		 * @param class 		the 'current' slide class
		 * @param dir prev|next direction of animation  
		 */
		function slide( base, className, dir, loop, nr, onStart, onEnd )
		{
			if ( lock ) return false;
			else lock = true;
			
			if( fol(dir) == 'first' )
			{
				// Unset current-slide and reset it
				$('.current-slide').removeClass( 'current-slide' );
				$('#viewport > #'+opts.slides+' > li:last').addClass( 'current-slide' );
				$('#viewport > #'+opts.slides+' > li:last > ul > li').addClass( 'current-subslide' );
				
				moveDown();
				
				// Calc the height that the slides has to animate down
				var amount = (opts.height * $('#viewport > #'+opts.slides+' > li').length) - opts.height;
				
				// If browser is IE, fix the amount
				if ( /MSIE/.test(navigator.userAgent) )
				{
					var ie_amount = $('#viewport > #'+opts.slides+' > li').length * 4;
					amount += ie_amount;
				}
				
				// Animate the slides
				$('#viewport > #'+opts.slides).animate({ top: '-'+amount+'px' }, 800, 'easeOutQuint', function()
				{
					lock = false;
					setProjectData();
				});		
				
				return false;
			}
			else if ( fol(dir) == 'last' )
			{
				// Unset current-slide and reset it
				$('.current-slide').removeClass( 'current-slide' );
				$('#viewport > #'+opts.slides+' > li:first').addClass( 'current-slide' );
				$('#viewport > #'+opts.slides+' > li:first > ul > li').addClass( 'current-subslide' );
				
				moveUp();
				
				// Animate the slides
				$('#viewport > #'+opts.slides).animate({ top: 0 }, 800, 'easeOutQuint', function()
				{
					lock = false;
					setProjectData();
				});		
				
				return false;
			}
			
			// from which direction should the next slide come?
			// prev & down = + (x or y) direction
			// next & up = - (x or y) direction
			if( dir == 'next' || dir == 'up' )
			{
				if( nr > 1 )
				{
					var mv = $( base + ' > li.' + className ).next().length ;
					//for( i=0;i<=nr;i++ )
					// hier loop door nr???
				}
				else var mv = $( base + ' > li.' + className ).next().length ;
					
				var dn = '-=';
			}
			else if( dir == 'prev' || dir == 'down' )
			{
				var mv = $( base + ' > li.' + className ).prev().length;
				var dn = '+=';
			}
			
			if( dir == 'up' || dir == 'down' )
				wh = 'height';
			else
				wh = 'width';
			
			// callback
			onStart();
			
			// Get the index of the current slide (CurrentSlideIndex)
			var csi = parseInt( $('#' + opts.slides + ' > li').index($('.current-slide')) );
			
			// Get the max of slides
			var msi = $('#' + opts.slides + ' > li').length - 1;
			
			// are there slides left?
			if( mv === 0 )
			{
				// Open the lock again
				lock = false;
				
				// Open next slide
				if ( dir == 'next' || dir == 'down' ) {
					// Stop further functioning if index is 0
					if ( csi == msi ) {
						lock = false; return;
					}
					
					return $( '.' + opts.nextSlide ).trigger( 'click' );
				} else {
					// Stop further functioning if index is 0
					if ( csi < 1 ) {
						lock = false; return;
					}
					
					// csi - 1 is previous slide (PreviousSlideIndex)
					var psi = csi-1;
					
					// Select the previous slide (PreviousSlide)
					var ps = $('#'+opts.slides+' > li:eq('+psi+') > ul');
					
					// Count the number of subslides (SubSlideCount)
					var ssc = ps.find('li').length;
					
					// Set the new positioning of the ul
					var newPos= (ssc-1)*opts.width;
					ps.css( 'left', '-'+newPos+'px' );
					opts.prevSubSlideHack = ps.find( 'li:last' );
					
					return $( '.' + opts.prevSlide ).trigger( 'click' );
				}
			}
			
			// Set alias for opts.height
			var oh = opts.height;
			
			// Increment opts.height with 5 to fix the IE bug
			if ( /MSIE/.test(navigator.userAgent) ) oh += 5;
			
			// css to animate
			if( wh == 'width' )	
				var css = { left : dn + opts.width + 'px', padding: '0px', margin: '0px'};
			else if( wh == 'height' )	
				var css = { top : dn + oh + 'px', padding: '0px', margin: '0px'};
			
//			console.log( $( base + ' > li.' + className ).offsetParent().offset() );
			
			$( base + ' > li.' + className ).parent().animate(
				css,
				opts.animationSpeed,
				opts.animationType,
				function()
				{
					if( dir == 'prev' || dir == 'down' )
					{
						
						$( base + ' > li.' + className )
							.removeClass( className )
							.prev()
							.addClass( className );
					}
					else if( dir == 'next' || dir == 'up' )
					{
						$( base + ' > li.' + className )
							.removeClass( className )
							.next()
							.addClass( className );
					}
						
					currentSlide = $( base + ' > li.' + className );
					lock = false;
						
					// callback
					onEnd();
				}
			);
		}
		
		
		function fixSubSlide(t)
		{
			// Remove old states
			$('.current-subslide').removeClass('current-subslide');
			
			// Check if the previous subslide hack needs to be applied
			if ( opts.prevSubSlideHack ) {
				// Add the class
				$(opts.prevSubSlideHack).addClass( 'current-subslide' );
				
				// Empty the hack
				opts.prevSubSlideHack = false;
			} else {
				// Add state to target
				$(t).addClass('current-subslide');
			}
		}
		
		
		function single( dir )
		{
			// Get number of items
			var count = $('viewport > #'+opts.slides+' > li').length;
			
			// Get number of subslides
			var subcount = $('viewport > #'+opts.slides+' > li:first > ul > li').length;
			
			// Get the active subslide
			var active = $('viewport > #'+opts.slides+' > li:first > ul > li').index( $('.active-subslide') );
			active++;
			
			// Return true if:
			// - There's one subslide
			// - Active subslide is the first or the last one
			if ( subcount < 2 || active == 1 || active == subcount )
				return true;
				
			return false;
		}
		
		
		function firstOrLast( dir )
		{
			// Set the currents
			var cs	= $('#viewport > #'+opts.slides+' > li.current-slide');
			var css	= $('#viewport > #'+opts.slides+' > li.current-slide > ul > li.current-subslide');
			
			// Get the index of the current project
			var i = $('#viewport > #'+opts.slides+' > li').index( cs );
			
			// Get the index of the current subslide
			var si = $('#viewport > #'+opts.slides+' > li.current-slide > ul > li').index( css );
			
			// Get the max index
			var m = $('#viewport > #'+opts.slides+' > li').length - 1;
			
			// Get the max index of subslides
			var sm = $('#viewport > #'+opts.slides+' > li.current-slide > ul > li').length - 1;
			
			if ( (dir == 'down' && i == 0) || (dir == 'prev' && i == 0 && si == 0 ) ) return 'first';
			if ( (dir == 'up' && i == m) || (dir == 'next' && i == m && si == sm ) ) return 'last';
			
			return false;
		}
		
		// Shorthand for FirstOrLast
		function fol( dir ) { return firstOrLast( dir ); }
	}
	
})(jQuery);
