(function($){
	$.fn.jSlide = function(options){
		options = $.extend({
			direction: 'vertical',
			speed: 600,
			easing: 'swing',
			loop: false,
			pos: 0
		}, options);
		
		// ================ Setup
		// ======================
		
		var $that = this.eq(0);
		var $film = $that.children('ul');
		var $orig = this;
		
		var curpos;
		
		var blocks = Math.ceil($film.children('li').length / options.items) -1;

		curpos = options.pos;
		if(options.pos > blocks){ curpos = blocks; };
		if(options.pos < 0){ curpos = 0; };
		
		var swidth = (options.direction=='vertical') ? options.width : options.width*(blocks+1);
		var sheight = (options.direction=='vertical') ? options.height*(blocks+1) : options.height;
		
		$that.css({
			overflow: 'hidden',
			position: 'relative',
			width: options.width,
			height: options.height
		});
		
		$film.css({
			position: 'absolute',
			listStyle: 'none',
			margin: 0,
			padding: 0,
			outline: 'none',
			top: 0,
			left: 0,
			width:swidth,
			height:sheight
		});
		
		$film.children('li').css({float:'left'});
		
		if(options.loop===false && curpos===0){
			$(options.back).css({visibility:'hidden'});
		};
		
		if(options.loop===false && curpos===blocks){
			$(options.next).css({visibility:'hidden'});
		};
		
		if(options.direction=="vertical"){
			$film.css({top: - curpos * options.height});
		}else{
			$film.css({left: - curpos * options.height});
		};

		// ================ Interaction
		// ============================
		
		var anim = function(){
			if(options.direction=="vertical"){
				$film.stop(true).animate({
					top: - curpos * options.height
				}, options.speed, options.easing, function(){ if(options.stop){options.stop();} });
			}else{
				$film.stop(true).animate({
					left: - curpos * options.width
				}, options.speed, options.easing, function(){ if(options.stop){options.stop();} });
			};
		};
		
		var backfn = function(source){
			
			if(options.slideshow && source!=="show"){
				clearInterval(slideshow.timer);
			};
						
			if(curpos > 0){
				curpos--;

			}else{
				if(options.loop===true){
					curpos = blocks;
				}else{
					curpos = 0;
				};
			};
			
			if(options.change){
				options.change({
					max: blocks,
					current: curpos
				});
			};
			
			if(options.slider){
				$(options.slider).slider('value', curpos);
			};
			
			anim();
			return false;
		};
		
		var nextfn = function(source){
			
			if(options.slideshow && source!=="show"){
				clearInterval(slideshow.timer);
			};
			
			if(curpos < blocks){
				curpos++;
			}else{
				if(options.loop===true){
					curpos = 0;
				}else{
					curpos = blocks;
				};
			};
			
			if(options.change){
				options.change({
					max: blocks,
					current: curpos
				});
			};
			anim();
			
			return false;
		};
		
		if(options.back){$(options.back).bind('click', backfn);};
		if(options.next){$(options.next).bind('click', nextfn);};
		
		
		// ================ Slideshow
		// ==========================
		
		if(options.slideshow){
			var so = options.slideshow;
			var slideshow = {};
			
			slideshow.time = 0;
			
			slideshow.init = function(){
				slideshow.timer = setInterval(function(){
					slideshow.time += so.delay;
					
					if(so.direction=="back"){
						backfn('show');
					}else{
						nextfn('show');
					};
					
					if(slideshow.time >= so.duration && so.duration!=0){
						clearInterval(slideshow.timer);
					};
				}, so.delay);
			};
			
			slideshow.init();
		};
		
		// ================ Public API
		// ===========================
		
		this.api = {};
		
		if(options.slideshow){
			this.api.slideshow = {};
			
			this.api.slideshow.stop = function(){
				clearInterval(slideshow.timer);
			};
		};
				
		this.api.get = function(){
			return {
				max: blocks,
				current: curpos
			};
		};
		
		this.api.go = function(pos){
			pos = parseInt(pos);
			if(pos > curpos){
				curpos = pos - 1;
				nextfn();
			}else if(pos < curpos){
				curpos = pos + 1;
				backfn();
			};
			
		};
		
		this.api.back = backfn;
		this.api.next = nextfn;
		
		this.api.change = function(opts){
			options = $.extend(options, opts);
		};
		
		return this;
	};
})(jQuery);











