/**
 * @author   Landon Springer
 * @date     09/29/08
 * @requires 'ui.core.js', 'ui.draggable.js' for dragging functionality
 *           'jquery.event.wheel-1.0.js' for mouse wheel scroll functionality
 */

(function($) {
	var defaults = {
        elasticity:35, // movement required to trigger animation
        height:200,
		minScrollHeight:40,
		wheel:true
    };
	$.fn.extend({
		scrollContainer:function(opts) {
			opts = $.extend(defaults, opts || {})
            $(this).each(function(){
				var self = this;
				$.fn._scrollContainerInit.apply(this, new Array(opts));
            });
		},
		_scrollContainerInit:function() {
			var self = $(this);
			var opts = arguments[0];
			self.data('ratio',opts.height/this.scrollHeight);
			var c = self.wrapInner(
				$("<div></div>")
					.css({
						position:'relative',
						marginRight:'20px',
						top:'0px'
					})
			);
			if (self.data('ratio') < 1) {
				var h = opts.height*self.data('ratio');
				h = h<opts.minScrollHeight?opts.minScrollHeight:h;
				self
					.data('ratio',h/opts.height)
				    .css({
						height: opts.height + 'px',
						overflow:'hidden',
						position: 'relative'
					})
					.data('containerHeight',$(this).height())
            		.data('dif',this.scrollHeight - self.data('containerHeight'));
				self.heightDif = opts.height-h;
				var p = $("<div></div>").prependTo(self);
				p.css({
					height: opts.height + 'px',
					position:'absolute',
					right:0
				})
				.append(
					$("<div>&nbsp;</div>")
						.addClass('scrollContainerScrollbar')
						.css({
							height:Math.floor(h)+'px'
						})
						.draggable({
							axis:'y',
							containment:'parent',
							appendTo:self,
							drag:function(e,ui) {
									$(this).parent().next().data('t',-$(this).css('top').replace('px','')/self.data('ratio'));
								},
							start:function() {
									$.fn._scrollContainerStart(this);
								},
							stop:function() {
								$(this).parent().next().data('scrolling',false);
							}
						})
				);
				self.scrollbar = $(".scrollContainerScrollbar",self);
				if(self.wheel && opts.wheel) {
					self.wheel(function(e,delta) {
						t = Number(self.scrollbar.css('top').replace('px',''))-(delta*10);
						t = t<0?0:t>self.heightDif?self.heightDif:t;
						self.scrollbar.css('top',t+'px');
						p.next().data('t',-t/self.data('ratio'));
						$.fn._scrollContainerStart(self.scrollbar);
						p.next().data('scrolling',false);
					})
					.scroll(function() {
						return false;
					});
				}
			}
		},
		_scrollContainerStart:function(o) {
			o = $(o).parent().next();
			o.data('v',0);
			o.data('a',.1);
			o.data('scrolling',true);
			$.fn._scrollContainerDoScroll(o);
		},
		_scrollContainerDoScroll: function(o) {
			var top, dif, dir, vDif;
			var rate = .1;
			var snap = 1;
			var a = 5;
			clearInterval(o.data('timer'));
			var t = setInterval(function() {
				top = parseFloat(o.css('top').replace('px',''));
				dif = o.data('t')-top;
				dir = dif/Math.abs(dif); // normalized direction vector
				vDif = Math.abs(dif*rate-o.data('v'))<a?dif*rate:a*dir+o.data('v'); // new velocity is rate * dif, up to a change of a units at a time, for easing
				o.data('v',vDif);
				if(Math.abs(dif)<snap && o.data('scrolling')===false) {
					o.data('v',dif);
					clearInterval(o.data('timer'));
					//$("body").append("<div>stop: "+o.data('t')+" : "+vDif+"</div>");
				}
				//$("body").append("<div>"+o.data('t')+"</div>");
				o.css('top',(top+o.data('v'))+'px');
			},10);
			o.data('timer',t);
			
		}
	});
})(jQuery);
