(function($, undefined) {
	$.widget('ui.kjVScrollbar', $.ui.slider, {
		options: {
			orientation: 'vertical',
			min: 0,
			max: 100,
			value: 100,
			wrapperClass: 'myWrapper',
			viewportClass: 'myViewport',
			sliderClass: 'mySlider',
			sliderWrapperClass: 'mySliderWrapper'
		},
		_create: function() {
			var self = this;
			this.options.slide = function(event, ui) {
				var topValue = -((100-ui.value)*self.difference/100);
				self.content.css('top', topValue+'px');
			};
			
			this.options.change = function(event, ui) {
				var topValue = -((100-ui.value)*self.difference/100);
				self.content.css('top', topValue+'px');
			};
			
			self.reverseValue = function() {
				return self.pxToValue(self.top());
			};
			
			self.top = function() {
				var t = self.content.css('top');
				t = t.substring(0, t.length-2);
				t = Number(t);
				t = isNaN(t) ? 0 : t;
				return t;
			};
			
			self.pxToValue = function(px) {
				return px*100/self.difference + 100;
			};
			
			self.maxTop = function() {
				return -((100)*self.difference/100);
			};
			
			this._initElements();
			
		},
		_initElements: function() {
			var content = this.element;
			var placeholder = $('<div/>');
			content.replaceWith(placeholder);
			$('body').append(content);
			var hasScrollbar = content.hasScrollbar();
			placeholder.replaceWith(content);
			//if (!hasScrollbar) return;
			
			this.content = content;
			var viewport = $('<div class="'+this.options.viewportClass+'"/>');
			content.wrap(viewport);
			//viewport = $('.myViewport');
			viewport = content.parent();
			var wrapper = $('<div class="' + this.options.wrapperClass + '"/>');
			viewport.wrap(wrapper);
			//wrapper = $('.myWrapper');
			wrapper = viewport.parent();
			this.wrapper = wrapper;
			var slider = $('<div class="' + this.options.sliderClass + '"/>');
			this.slider = slider;
			this.element = slider;
			
			var sliderWrapperClass = this.options.sliderWrapperClass;
			var sliderWrap = $('<div class="' + sliderWrapperClass + '"/>');
			this.sliderWrap = sliderWrap;
			sliderWrap.append(slider);
			sliderWrap.insertAfter(viewport);
			sliderWrap.hide();
			
			$.ui.slider.prototype._create.apply(this, arguments);
			
			var a = slider.find('a');
			a.noFocus();
			
			var difference, proportion, handleHeight;
			
			this.viewport = viewport;
			var self = this;

			this.refresh = function() {
				if (!this.contentHeight) {
					var contentParent = viewport.parent();
					$('body').append(viewport);
					this.contentHeight = content.innerHeight();
					this.contentWidth = content.innerWidth();
					viewport.css('height', this.contentHeight);
					viewport.css('width', this.contentWidth);
					viewport.css('overflow', 'hidden');
					content.css({height:'auto', overflow:'visible', position:'relative'});
				} else {
					var contentParent = viewport.parent();
					$('body').append(viewport);
				}
				difference = content.outerHeight(true) - viewport.height() + 4;
				var sliderWrapVisible;
				if (difference < 0) {
					sliderWrapVisible = false;
					sliderWrap.hide();
				} else {
					sliderWrap.show();
					sliderWrapVisible = true;
				}
				proportion = difference / content.height();
				handleHeight = Math.round((1-proportion)*viewport.height());
				handleHeight -= handleHeight%2;
				wrapper.width(viewport.width()+sliderWrap.outerWidth());
				
				a.height(handleHeight);
				var ah = a.outerHeight();
				var sh = viewport.height()-Math.max(ah);
				var sm = Math.max((viewport.height()-sh)/2);
				slider.css({'height': sh+ 'px', marginTop:sm + 'px'});
				a.css({marginBottom:'-'+(Math.round(ah/2))+'px', width:sliderWrap.width()-2+'px'});
				sliderWrap.css('height', viewport.height() + 'px');
				
				contentParent.append(viewport);
				
				//self.value(100);
				
				this.difference = difference;
				
				var t = self.content.css('top');
				t = t.substring(0, t.length-2);
				
				if (sliderWrapVisible) {
					if (Number(t) < self.maxTop()) {
						self.content.animate({top:self.maxTop()}, 200);
					} else {
						var r = self.reverseValue();
						if (!isNaN(r)) {
							self.value(r);
						}
					}
				} else if (!sliderWrapVisible && Number(t) < 0) {
					self.content.animate({top:0}, 200);
				}
				
			};
			
			this.refresh();
			
			
			wrapper.mousewheel(function(event, delta, deltaX, deltaY) {
				if (self.difference <= 0) return true;
				var speed = 4;
				var sliderVal = self.value();
				if (sliderVal <= 0 && deltaY < 0 || sliderVal >= 100 && deltaY > 0) {
					return true;
				}
				sliderVal += (deltaY*speed);
				self.value(sliderVal);
				event.preventDefault;
				return false;
			});
			
			$.fn.oneFingerScroll = function() {
				var scrollStartPos = 0;
				$(this).bind('touchstart', function(e){
					if (self.difference < 0) return; // do nothing if scrollbar not visible
					var oe = e.originalEvent;
					var scrollTop = $(this).scrollTop();
					var top = self.top();
					var pageY = oe.touches[0].pageY;
					scrollStartPos = pageY;//$(this).scrollTop();
					//console.log('touchstart', 'pageY:'+pageY, 'top:'+top, 'scrollTop:'+scrollTop, 'scrollStartPos:'+scrollStartPos);
					//scrollStartPos = $(this).scrollTop() + oe.touches[0].pageY;
					if ($(e.target).hasClass('ui-slider-handle'))
						e.preventDefault();
				});
				$(this).bind('touchmove', function(e){
					if (self.difference < 0) return; // do nothing if scrollbar not visible
					var oe = e.originalEvent;
					var pageY = oe.touches[0].pageY;
					var top = self.top();
					var scrollDiff = scrollStartPos - pageY;
					var rv = self.reverseValue();
					//console.log('touchmove', 'pageY:'+pageY, 'top:'+top, 'scrollDiff:'+scrollDiff, 'reverseValue:'+rv, 'value:'+v); 
					if ($(e.target).hasClass('ui-slider-handle')) {
						var v = self.pxToValue(scrollDiff + top);
					} else if ($(e.target).parent('.myViewport')) {
						var v = self.pxToValue(-scrollDiff + top);
					} else {
						return;
					}
					if (v < 0) v = 0;
					else if (v > 100) v = 100;
					
					self.value(v);
					e.preventDefault();
				});
				return this;
			}
			
			/*
			wrapper.bind('drag', function(e) {
				if (self.difference <= 0) return true;
				var speed = 4;
				var sliderVal = self.value();
				if (sliderVal <= 0 && deltaY < 0 || sliderVal >= 100 && deltaY > 0) {
					return true;
				}
				sliderVal += (deltaY*speed);
				self.value(sliderVal);
				event.preventDefault;
				return false;
			});
			*/
			
			wrapper.oneFingerScroll();
			
			slider.click(function(event){
				event.stopPropagation();
			});
			
			sliderWrap.click(function(event) {
				var offsetTop = $(this).offset().top;
				var clickValue = (event.pageY - offsetTop) * 100 / $(this).height();
				self.value(100-clickValue);
			});
		}
	});
})( jQuery );

