(function($) {

$.widget("ui.vv_smoothscroll", {
		
	init: function(){
		 var instance = this;
		 // build scroller
		 instance._build();
		 // initialize data
		 instance.setData('topHSHeight', 0);
		 instance.setData('bottomHSHeight', 0);
		 instance.setData('topOffset', instance.element.offset().top);
		 instance.setData('booster', 1);
		 instance._setScrollableAreaHeight();
		 instance.doScrollBottom = this._getDoScrollBottom(instance);
		 instance.doScrollTop = this._getDoScrollTop(instance);		 
	},
	
	// initializing
	
	_build: function() {
		var instance = this;
		var o = instance.options;
		var el= instance.element;
		
		el.vv_makePositioned();

		el.children().wrapAll('<div class="scrollableArea"></div>')
		el.find('.scrollableArea').css({
				position: 'relative',
				width	: 'auto',
				height	: 'auto'
			});
		
		el.children().wrapAll('<div class="scrollWrapper"></div>');
		var scrollWrapper = el.find('.scrollWrapper');
		scrollWrapper.css({
				position: 'relative',
				zIndex	: '199',
				overflow: 'hidden',
				width	: '100%',
				height	: '100%'
		});
		$('<div class="topHotSpot"></div>')
			.css({
				position	: 'absolute',
				zIndex		: '200',
				top			: o.topHotSpotPos,
				width		: '100%',
				height		: o.topHotSpotHeight,
				background	: 'url(' + o.resourcePath + 'transparent.gif) repeat',
				cursor		: 'url(' + o.resourcePath + 'cursor_arrow_top.ico), n-resize'
			})
			.bind('mousemove', instance, instance._onTopMouseMove)
			.bind('mouseover', instance, instance._onTopMouseOver)
			.bind('mouseout', instance, instance._onTopMouseOut)
			.bind('mousedown', instance, instance._onMouseDown)
			.bind('mouseup', instance, instance._onMouseUp)
			.appendTo(el);
		
		$('<div class="bottomHotSpot"></div>')
			.css({
				position	: 'absolute',
				zIndex		: '200',
				bottom		: o.bottomHotSpotPos,
				width		: '100%',
				height		: o.bottomHotSpotHeight,
				background	: 'url(' + o.resourcePath + 'transparent.gif) repeat',
				cursor		: 'url(' + o.resourcePath + 'cursor_arrow_bottom.ico), s-resize'
			})
			.bind('mousemove', instance, instance._onBottomMouseMove)
			.bind('mouseover', instance, instance._onBottomMouseOver)
			.bind('mouseout', instance, instance._onBottomMouseOut)
			.bind('mousedown', instance, instance._onMouseDown)
			.bind('mouseup', instance, instance._onMouseUp)
			.appendTo(el);
			
		$(window).bind('resize', instance, instance._onWindowResize);
	},
	
	_setScrollableAreaHeight: function() {
		
		var scHeight = 0;
		var scArea = this.element.find('.scrollableArea');
		scArea.children(this.options.itemClass).each(function() {
			scHeight = scHeight + $(this).outerWidth(true);		
		});
		scArea.css("width", scHeight + "px");
		this.setData('scrollableAreaHeight', scHeight);
	},

	// scroll methods
	
	_getDoScrollBottom: function(instance) {
		return function(){
			var scWrapper = instance.element.find('.scrollWrapper');
			scWrapper.scrollTop(scWrapper.scrollTop() + 
				(instance.getData('scrollYpos') * instance.getData('booster')));
			instance._showHideHotSpots();
		}
	},
	
	_getDoScrollTop: function(instance) {
		return function() {
			var scWrapper = instance.element.find('.scrollWrapper');
			scWrapper.scrollTop(scWrapper.scrollTop() - 
				(instance.getData('scrollYpos') * instance.getData('booster')));
			instance._showHideHotSpots();
		}
	},	

	
	// bottom events
	_onBottomMouseMove: function(e) {
		var instance = e.data;
		var y = e.pageY - $(this).offset().top;
		y = Math.round(y/(instance.getData('bottomHSHeight')/15));
		instance.setData('scrollYpos', y);
	},
	
	_onBottomMouseOver: function(e) {
		var instance = e.data;
		instance.setData('bottomScrollInterval', setInterval(instance.doScrollBottom, 15));
	},
	
	_onBottomMouseOut: function(e) {
		var instance = e.data;
		clearInterval(instance.getData('bottomScrollInterval'));
		instance.setData('scrollYpos', 0);
	},
	
	// top events
	_onTopMouseMove: function(e) {
		var instance = e.data;
		var topHotSpot = instance.element.find('.topHotSpot');
		var y = $(this).offset().top + topHotSpot.innerHeight() - e.pageY;
		y = Math.round(y/(instance.getData('topHSHeight')/15));
		instance.setData('scrollYpos', y)
	},
	
	_onTopMouseOver: function(e) {
		var instance = e.data;
		instance.setData('topScrollInterval', setInterval(instance.doScrollTop, 15));
	},
	
	_onTopMouseOut: function(e) {
		var instance = e.data;
		clearInterval(instance.getData('topScrollInterval'));
		instance.setData('scrollYpos', 0);

	},
	
	// common hot spot events
	_onMouseDown: function(e) {
		var instance = e.data;
		instance.setData('booster', instance.options.mouseDownSpeedBooster);
	},
	
	_onMouseUp: function(e) {
		var instance = e.data;
		instance.setData('booster', 1);
	},
	
	// window resize event
	
	_onWindowResize: function(e) {
		var instance = e.data;
		//recalculate the height of the scrollable area
		instance._setScrollableAreaHeight();
		// Reset the top offset of the scroll wrapper
		instance.element.find('.scrollWrapper').scrollTop('0');
		// If the scrollable area is shorter than the current
		// window height, both scroll hotspots should be hidden.
		// Otherwise, check which hotspots should be shown.
		var bodyHeight = $("body").innerHeight();
		if(instance.getData('scrollableAreaHeight') < bodyHeight) {
			instance._hideBottomHotSpot();
			instance._hideTopHotSpot();
		}
		else
			instance._showHideHotSpots();
	},
	
	// hot spot hiding/showing
	
	_hideBottomHotSpot: function () {
		this.element.find('.bottomHotSpot').hide();
		// to force recalculate height at next show call
		this.setData('bottomHSHeight', 0); 
	},

	_hideTopHotSpot: function() {
		this.element.find('.topHotSpot').hide();
		// to force recalculate height at next show call
		this.setData('topHSHeight', 0); 
	},
			
			
	_showTopHotSpot: function () {
		var topHotSpot = this.element.find('.topHotSpot');
		topHotSpot.show();
		// Recalculate the hotspot height
		if( this.getData('topHSHeight') <= 0)
			this.setData('topHSHeight', topHotSpot.height());
	},
			
	_showBottomHotSpot: function () {
		var bottomHotSpot = this.element.find('.bottomHotSpot');
		bottomHotSpot.show();
		// Recalculate the hotspot height
		if( this.getData('bottomHSHeight') <= 0)
			this.setData('bottomHSHeight', bottomHotSpot.height());
	},

	_showHideHotSpots: function() {

		var scWrapper = this.element.find('.scrollWrapper');
				
		// can't scroll further top
		if(scWrapper.scrollTop() === 0)
		{
			this._hideTopHotSpot();
			this._showBottomHotSpot();
			//window.status = 'hide top (scrollTop: ' + scWrapper.scrollTop() + ')';  
		}
		// can't scroll further bottom
		else if(this.getData('scrollableAreaHeight') <= scWrapper.innerHeight() + scWrapper.scrollTop())
		{
			this._hideBottomHotSpot();
			this._showTopHotSpot();
			//window.status = 'hide bottom (scrollTop: ' + scWrapper.scrollTop() + ')';
		}
		// in the middle of the scrolling
		else
		{
			this._showBottomHotSpot();
			this._showTopHotSpot();
			//window.status = 'show both (scrollTop: ' + scWrapper.scrollTop() + ')';
		}

	}

});

$.extend($.ui.vv_smoothscroll, {
	getter: [],
	defaults: {
		resourcePath			: '/html/js/ext/images/smoothscroll/',
		topHotSpotPos			: '0',
		topHotSpotHeight		: '15%',
		bottomHotSpotPos		: '0',
		bottomHotSpotHeight		: '15%',
		mouseDownSpeedBooster	: 1
	}
});

})(jQuery);