/* 
 * jDragSlide
 * Author:  Christoph Stickel <mixer2@gmail.com>
 * License: Released under MIT License
 * 
 */
 
(function($) {

$.fn.jDragSlide = function(options) {
	var settings = $.extend({}, $.fn.jDragSlide.defaults, options);
	
	var history = [];
	var container = this;
	var slideElement = $(this).children(':first');
	
	function limitViolation(position) {
		var limits = {
			"right": -1*(slideElement.width()-container.width())-settings.limit,
			"left": settings.limit
			};
		if(position.left > limits.left) slideElement.css("left", limits.left);
		else if(position.left < limits.right)  slideElement.css("left", limits.right);		
		else return false;
	}
	
	function relax(position) {
		var returnTo = false;

		if(position.left > 0) returnTo = 0;
		else if(position.left < -1*(slideElement.width()-container.width())) returnTo = -1*(slideElement.width()-container.width());
		
		if(returnTo !== false) slideElement.animate({'left': returnTo+'px'}, {
			"duration":settings.limitDuration,
			"easing":settings.limitEasing
		});
	}
	
	function start(e, ui) {
		slideElement.stop();
		
		history = [];
		history.push({
			"offset":ui.offset,
			"time": new Date().getTime()
		});
				
		settings.start(e, ui);
	}
	
	function stop(e, ui) {		
		var speed = 0;
		var now = new Date().getTime();
				
		var last = history.shift();
		$.each(history, function() {
			if(now-settings.smoothTolerance > this.time) return false;
			speed += (last.offset.left-this.offset.left)/(this.time-last.time);
			last = this;
		});
		
		var factor = Math.sqrt(Math.abs(speed));
	
		if(speed == 0) {
			relax(ui.position);
		} else {
			var inverter = 1;
			if(speed > 0) inverter = -1;
			
			ui.position.left += inverter*settings.smoothFactor*factor;
						
			slideElement.animate({'left': ui.position.left+'px'}, {
				"duration":settings.smoothDuration*factor,
				"easing": settings.smoothEasing,
				"step": function() {
					var position = {
						"left": parseInt(slideElement.css('left')),
						"top": parseInt(slideElement.css('top'))
						};
						
					if(limitViolation(position) !== false) {
						slideElement.stop();
						relax(ui.position);
						}
					},
				"complete": function() { relax(ui.position); }
			});

		}
		
		settings.stop(e, ui);
	}

	function drag(e,ui) {
		var time = new Date().getTime();
		if(history.length > 3) history.shift();
		history.push({
				"offset":ui.offset,
				"time": time
			});
					
		if(limitViolation(ui.position) !== false) return false;
		settings.drag(e, ui);
	}

	slideElement.css('left', settings.offset+'px').draggable({
		"axis":settings.axis,
		"drag":drag,
		"start": start,
		"stop": stop
	});
	
	return this;
};

$.fn.jDragSlide.defaults = {
		"axis":false,
		"handle":false,
		"offset": 0,
		"limit": 150,
		"limitEasing": 'easeOutElastic',
		"limitDuration": 1500,
		"smoothFactor": 200,
		"smoothEasing": 'easeOutQuad',
		"smoothDuration": 150,
		"smoothTolerance": 180,
		"start": $.noop,
		"stop": $.noop,
		"drag": $.noop
	  };

})(jQuery);
