/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */
 
 /**
 * This jQuery plugin creates an animated slider with the child elements as frames.
 
 simpleslider
	create/modify/register required markup
		wrapper - simply wraps all elements, no functionality
		boundary - encloses all children elements, shows only a single frame
		container - holds all frames, distrubutes them in correct order/position
		frames
	create requested controls
		prev/next
		navigation
	execute transition
		slide
			easing
			direction
		fade
		cut
	modify controls when necessary
	set timer for automatic transition
	
	
 *
 * @author Justin Jones (justin(at)jstnjns(dot)com)
 * @version 1.4
 *
 * New features in 1.4
 *  - Added support for navigation (set to true by default, so you'll need
 *    to manually turn this off if not wanted and updating)
 * 
 * New Features in 1.3:
 *  - Cleaned up codebase (check to see if the settings you are implimenting
 *    not deprecated or changed, as well as CSS [revamped a lot])
 *  - Changed buttons to anchor tags for better CSS flexibility
 *  - Added 'fade' and 'cut' transitions
 *
 * New Features in 1.2:
 *  - Easing
 *  - Multiple instances can now run on the same page
 *
 * New Features in 1.1:
 * 	- Vertical scrolling
 * 	- Buttons are optional
 * 	- Speed settings
 *
 */
(function($){
	$.fn.simpleslider = function(settings) {
		
		var defaults = {
			transition		: 'slide', // cut, fade
			easing			: 'swing', // linear
			direction		: 'horizontal', // for 'slide' style transition
			speed			: 500, // for 'slide' and 'fade' style transitions
			auto			: false,
			interval		: 2000, // pause between transitions if 'auto' is set to TRUE
			hoverPause		: true,
			navigation		: true,
			buttons			: true,
			prevText		: 'Previous',
			nextText		: 'Next',
			loop			: true
		};
		
		settings = $.extend({}, defaults, settings); 
		
		$(this).each(function() {
			// ----------------------------------------------------------------|| Setting Vars ||
			var $this = $(this),
			$frames,
			$wrapper,
			$boundary,
			$container,
			$prev,
			$next,
			$navigation,
			boundaryWidth,
			boundaryHeight,
			frameWidth,
			frameHeight,
			frameCount,
			currentFrame = 1,
			auto,
			
			_init = function() {
									
				$frames			= $this
									.children()
									.addClass('slider-slide');
							
				// Get values and dimensions necessary for more advanced structure
				frameCount		= $frames.length;
				
				frameWidth		= 0;
				frameHeight		= 0;
				
				boundaryWidth	= 0;
				boundaryHeight	= 0;
				
				// Set up the basic physical structure of the slider
				$wrapper		= $this
									.wrap('<div />')
										.parent()
										.addClass('slider-wrapper');
								
				$boundary		= $this
									.wrap('<div />')
										.parent()
											.addClass('slider-boundary');
									
				$container		= $this
									.addClass('slider-container');
								
				if(settings.buttons) {
					$prev		= $('<a />')
									.addClass('slider-control-prev')
									.text(settings.prevText)
									.click(function(e){ 
										e.preventDefault()
										
										if(!$this.hasClass('disabled')) {
											_transition(currentFrame - 1);
										}
									 });
								
					$next		= $('<a />')
									.addClass('slider-control-next')
									.text(settings.nextText)
									.click(function(e){
										e.preventDefault();
										
										if(!$this.hasClass('disabled')) {
											_transition(currentFrame + 1);
										}
									});
								
					$wrapper
						.prepend($prev)
						.append($next);
				}
				
				if(settings.navigation) {
					$navigation = $('<ol />')
									.addClass('slider-control-navigation');
									
					$frames.each(function(i, frame) {
						var $tab = $('<li />')
										.addClass('slider-control-navigation-tab')
											.append('<span />').find('span')
												.addClass('number')
												.text(i + 1)
												.end()
										.click(function(e) {
											e.preventDefault();
											
											if((i+1) != currentFrame) {
												_transition(i+1);
												console.log(i+1);
											}
										});
										
						if(i == 0) {
							$tab
								.addClass('current');
						}
						
						if($(frame).attr('title')) {
							$('<span />')
								.addClass('title')
								.text($(frame).attr('title'))
								.appendTo($tab)
						}
										
						$navigation
							.append($tab);
					});
									
					$wrapper
						.append($navigation);
				}
				
				// if(settings.navigation) {
				// 	var tab = {};
				// 	
				// 	$navigation		= $('<ol />')
				// 						.addClass('slider-control-navigation');
				// 						
				// 	$frames.each(function(i) {
				// 		tab[i] = i;
				// 	})
				// }
				
				$frames.each(function() {
					if($(this).width() > frameWidth) frameWidth = $(this).width(); // Get widest frame's width
					if($(this).height() > frameHeight) frameHeight = $(this).height(); // Get tallest frame's height
					
					if($(this).outerWidth(true) > boundaryWidth) boundaryWidth = $(this).outerWidth(true); // Get widest frame's outer width
					if($(this).outerHeight(true) > boundaryHeight) boundaryHeight = $(this).outerHeight(true); // Get tallest frame's outer height
				});
				
				// Set dimensions on elements that need sizing
				$frames.css({
					width	: frameWidth,
					height	: frameHeight,
					float	: 'left'
				});
				
				if(settings.transition == 'slide') {
					if(settings.direction == 'horizontal') {
						$container.css({
							width	: boundaryWidth * frameCount,
							height	: boundaryHeight,
							overflow: 'hidden'
						});
					} else {
						$container.css({
							width	: boundaryWidth,
							height	: boundaryHeight * frameCount,
						overflow: 'hidden'
						});
					}
				} else {
					$container.css({
						position: 'relative',
						width	: boundaryWidth,
						height	: boundaryHeight
					});
					
					$frames
						.css({
							position: 'absolute',
							left	: 0,
							top		: 0
						})
						.hide();
					
					$frames.eq(0)
						.show();
				}
					
				$boundary.css({
					width	: boundaryWidth,
					height	: boundaryHeight,
					overflow: 'hidden'
				});
				
				if(settings.auto) {
					_startTimer(settings.interval);
					
					if(settings.hoverPause) {
						$wrapper.hover(function() {
							_stopTimer();
						}, function() {
							_startTimer();
						});
					}
				}
				
			},

			// Transitions to frame
			_transition = function(toFrame) {
				
				// LOOPING
				// If out of bounds, send to the opposite side
				if(settings.loop) {
					if(toFrame > frameCount) {
						_transition(1);
						return;
					} else if(toFrame <= 0) {
						_transition(frameCount);
						return;
					}
					
				// NON-LOOPING
				// If out of bounds, do nothing
				} else {
					if(toFrame > frameCount || toFrame <= 0) return;
				}
				
				switch(settings.transition) {
					case 'slide':
						var diff = toFrame - currentFrame;
						_slide(diff);
						break;
						
					case 'fade':
						_fade(toFrame);
						break;
						
					default:
						_cut(toFrame);
						break;
				}
				
				currentFrame = toFrame;
				
				/*
					TODO get the button disabling / enabling and looping to work
				*/
				if(!settings.loop && settings.buttons) {
					// Sets 'previous' button to disabled if on first frame
					if(currentFrame == 1) {
						$prev.addClass('disabled');
					} else {
						$prev.removeClass('disabled');
					}
						
					// Sets 'next' button to disabled if on last frame
					if(currentFrame == frameCount) {
						$next.addClass('disabled');
					} else {
						$next.removeClass('disabled');;
					}
				}
				
				if(settings.navigation) {
					$navigation
						.children()
							.removeClass('current')
							.eq(currentFrame - 1)
								.addClass('current');
							
					console.log(currentFrame - 1);
				}
				
			},
			
			_slide = function(frames) {
				
				if(settings.direction == 'horizontal') {
					$this.stop().animate({
						marginLeft: (-1) * (currentFrame + frames - 1) * boundaryWidth + 'px'
					}, settings.speed, settings.easing);
				} else if(settings.direction == 'vertical') {
					$this.stop().animate({
						marginTop: (-1) * (currentFrame + frames - 1) * boundaryHeight + 'px'
					}, settings.speed, settings.easing);
				}
				
			},
			
			_fade = function(toFrame) {
				
				$frames.eq(toFrame - 1)
					.fadeIn(settings.speed);
					
				$frames.eq(currentFrame - 1)
					.fadeOut(settings.speed);
				
			},
			
			_cut = function(toFrame) {
				
				$frames.eq(toFrame - 1)
					.show();
					
				$frames.eq(currentFrame - 1)
					.hide();
					
			},

			_startTimer = function() {
				auto = setInterval(function() {
					_transition(currentFrame + 1);
				}, settings.interval);
			},
			
			_stopTimer = function() {
				if(settings.auto !== false){
					clearInterval(auto);
				}
			}
			
			_init();
		});
	}
})(jQuery);


$(function() {
	
	$('#slider').simpleslider({
		easing			: 'swing',
		navigation		: false
	});
	
});
