(function($){
	$.fn.gridscroll = function(){
		var oSlider = $(this);
		var oViewport = $('.viewport', oSlider);
		var oContent = $('.overview', oSlider);
		var oPages = oContent.children();
		var oBtnLeft = $('.left', oSlider);
		var oBtnRight = $('.right', oSlider);
		var oBtnUp = $('.up', oSlider);
		var oBtnDown = $('.down', oSlider);
				
		var iPage = {}, iSteps, iCurrent, oTimer, iColumn = 3, lastPoint = { x: 0, y: 0};

		function initialize(){
			iPage.x = $(oPages[0]).outerWidth(true);
			iPage.y = $(oPages[0]).outerHeight(true);
			iSteps = oPages.length;
			iCurrent = Math.floor(Math.random() * iSteps);
			move(1);
			setEvents();
			setTimer();
		}
		function setEvents(){
			if(oBtnLeft.length > 0 && oBtnRight.length > 0){
				oBtnLeft.click(function(){move(-1,'x'); return false;});
				oBtnRight.click(function(){move(1,'x'); return false;});
				oBtnUp.click(function(){move(-iColumn,'y'); return false;});
				oBtnDown.click(function(){move(iColumn,'y'); return false;});	
				$(oContent).mousedown(start);
			}
		}
		function start(oEvent){
			clearTimeout(oTimer);
			$(document).mousemove(drag);
			document.onmouseup = end;
			$(oContent).mouseup(end);
			
			lastPoint.y = oEvent.pageY ;
			lastPoint.x = oEvent.pageX;
			return false;
		};		
		
		function end(oEvent){
			$(document).unbind('mousemove',drag);
			document.onmouseup = null;
			$(oContent).unbind('mouseup', end);
			
			clearTimeout(oTimer);
			calculateMove();
			setTimer();
			return false;
		};			
		function setTimer(){
			oTimer = window.setTimeout(function(){
				iCurrent = Math.floor(Math.random() * iSteps);
				move(1,'y',true);
			}, 3000);
		}
		
		function drag(oEvent){
			var deltaX = Math.min(0, Math.max(-540,parseInt(oContent.css('left')) + oEvent.pageX - lastPoint.x));
			var deltaY = Math.min(0, Math.max(-500,parseInt(oContent.css('top')) + oEvent.pageY - lastPoint.y));
			
			$(oContent).css({ 'left': deltaX, 'top': deltaY });

			lastPoint.x = oEvent.pageX;;
			lastPoint.y = oEvent.pageY;
			
			return false;
		};		
		
		function move(iDirection, sAxis, bTimer){
			clearTimeout(oTimer);
			
			/* Circular left */
			iCurrent = iCurrent == 1 && iDirection == -1 ? iSteps +1 : iCurrent;
			
			/* Circular right */
			iCurrent = iCurrent == iSteps && iDirection == 1 ? 0 : iCurrent;
			
			/* Circular down */
			if( Math.ceil((iCurrent + iDirection) / iColumn) == iColumn+1 && iDirection == iColumn) {
				iCurrent = (iCurrent % iColumn);
				iDirection = 1;
			}
			
			/* Circular up */
			if( Math.ceil((iCurrent + iDirection) / iColumn) == 0  && iDirection == -iColumn) {
				iCurrent = (iColumn * iColumn -iColumn) +iCurrent;
				iDirection = -1;
			}
			
			if(iCurrent + iDirection > 0 && iCurrent + iDirection <= iSteps){
				iCurrent += iDirection;
				var bAxis = sAxis == 'x';

				var oPosition = {};
				oPosition.left = -$(oPages[iCurrent -1]).position().left
				oPosition.top = -$(oPages[iCurrent -1]).position().top

				oContent.animate(oPosition,{queue: false});
				if(bTimer){setTimer();}
			}
		}
		
		function calculateMove(){
			var iLeft = Math.abs(parseInt(oContent.css('left')));
			var iTop = Math.abs(parseInt(oContent.css('top')));
			var iRow = Math.round(iLeft / iPage.x);
			var iCol = Math.round(iTop / iPage.y);
	
			var oPosition = {};
			oPosition.left = -iRow * iPage.x;
			oPosition.top = -iCol * iPage.y;
			iCurrent = iCol * 3 + iRow +1;
			oContent.animate(oPosition,{queue: false});
		};
			
		
		initialize();
	};
})(jQuery);
