(function($) {

$.fn.scrollSlide = function(options) {

	var settings = $.extend({}, {
		itemClass: '',
		scrollPrev: '',
		scrollNext: '',
		direction: 'vertical',
		orientation: 'next',
		startout: 0,
		velocity: 0,
		duration: 5000,
		timeout: 0
	}, options);

	return this.each(function() {
		var ele = this, $pane = $(this), $items, data;
		var len, prev, prev0, next, cur0, cur, last, dir0, dir, done, pause, reverse, t1;
		eval('data='+$pane.attr('data'));
		ele.data = $.extend({}, settings, data);
		if( ele.data.scrollPrev ) {
			ele.data.scrollPrev = '#'+ele.data.scrollPrev.replace(':','\\:');
		}
		if( ele.data.scrollNext ) {
			ele.data.scrollNext = '#'+ele.data.scrollNext.replace(':','\\:');
		}

		$items = $pane.find('.'+ele.data.itemClass);
		if($items.length <= 1) return false;
		cur = 0;
		done = true;
		reverse = false;
		pause = false;
		ele.t1 = null;
		itemHeight = $items.eq(0).height();
		itemWidth = $items.eq(0).width();
		reset_o();
		switch(ele.data.orientation){
		case 'prev' :
			dir0 = dir = -1;
			if( ele.data.startout ) {
			ele.t1 = setTimeout(function(){
				scrollPrev();}, ele.data.startout);
			} else {
				scrollPrev();
			}
			break;
		case 'next' :
			dir0 = dir = 1;
			if( ele.data.startout ) {
			ele.t1 = setTimeout(function(){
				scrollNext();}, ele.data.startout);
			} else {
				scrollNext();
			}
			break;
		default :
		}

		function reset_o(){//before each animation, reset to (0,0), skip this.
			$pane.stop(true).attr({scrollLeft:0, scrollTop:0});
		};

		$pane.mouseenter(function(){
			//~ console.log("jquery.scrollSlide.js:66:mouseenter");
			clearTimeout(ele.t1);
			pause = true;
			$pane.stop(true);
		});

		$pane.mouseleave(function(){
			//~ console.log("jquery.scrollSlide.js:72:mouseleave");
			if( dir == 1 ) {
				prev = prev0;
				if( !done && dir0 != dir ) {
					cur = (cur-1 >= 0) ? cur-1 : $items.length-1;
					reverse = true;
				}
				if( done || pause || dir0 != dir ) {
					dir0 = dir;
					$pane.stop(true);
					prev0 = prev;
					prev = cur;
					next = (cur-1 >= 0) ? cur-1 : $items.length-1;
					scrollNext();
				}
			}
			else if( dir == -1 ) {
				prev = prev0;
				if( !done && dir0 != dir ) {
					cur = (cur+1 < $items.length) ? cur+1 : 0;
					reverse = true;
				}
				if( done || pause || dir0 != dir ) {
					dir0 = dir;
					$pane.stop(true);
					prev0 = prev;
					prev = (cur-1 >= 0) ? cur-1 : $items.length-1;
					next = (cur+1 < $items.length) ? cur+1 : 0;
					scrollPrev();
				}
			}
		});

		$(ele.data.scrollPrev).bind('mousedown', 1, function(e){
			dir = 1;
			prev = prev0;
			if( !done && dir0 != dir ) {
				cur = (cur-1 >= 0) ? cur-1 : $items.length-1;
				reverse = true;
			}
			if( done || pause || dir0 != dir ) {
				clearTimeout(ele.t1);
				dir0 = dir;
				$pane.stop(true);
				scrollNext();
			}
		});

		$(ele.data.scrollNext).bind('mousedown', -1, function(e){
			dir = -1;
			prev = prev0;
			if( !done && dir0 != dir ) {
				cur = (cur+1 < $items.length) ? cur+1 : 0;
				reverse = true;
			}
			if( done || pause || dir0 != dir ) {
				clearTimeout(ele.t1);
				dir0 = dir;
				$pane.stop(true);
				scrollPrev();
			}
		});

		function scrollNext() {
			// because the $item jQuery list will be reorder the internal index
			if( $('.'+ele.data.itemClass).not($items).length ) {
				$items = $items.add($('.'+ele.data.itemClass).not($items));
				cur=0;prev =0;next=0;
			}
			prev0 = prev;
			prev = (cur-1 >= 0) ? cur-1 : $items.length-1;
			next = (cur+1 < $items.length) ? cur+1 : 0;
			switch (ele.data.direction) {
			case 'horizontal':
				speed = Math.abs((ele.data.duration - ele.data.velocity)/itemWidth * ($items.eq(next).offset().left - $pane.offset().left));
				break;
			case 'vertical':
				speed = Math.abs((ele.data.duration - ele.data.velocity)/itemHeight * ($items.eq(next).offset().top - $pane.offset().top));
				break;
			default:
			}

			done = false;
			pause = false;
			//~ console.log("jquery.scrollSlide.js:157:font:"+$items.eq(next).find('font').text());
			$pane.scrollTo($items.eq(next), {
				duration: speed,
				easing: 'linear',
				onAfter: function() {
					$items.eq(prev).after($items.eq(cur));
					$pane.scrollTo($items.eq(next));
					cur = next;
					prev = (cur-1 >= 0) ? cur-1 : $items.length-1;
					done = true;
					if( ele.data.timeout ) {
						ele.t1 = setTimeout(function(){
						scrollNext();
						}, ele.data.timeout);
					} else {
						scrollNext();
					}
				}
			});

		}

		function scrollPrev() {
			// because the $item jQuery list will be reorder the internal index
			if( $('.'+ele.data.itemClass).not($items).length ) {
				$items = $items.add($('.'+ele.data.itemClass).not($items));
				cur=0;prev =0;next=0;
			}
			prev0 = prev;
			prev = cur;
			next = (cur-1 >= 0) ? cur-1 : $items.length-1;
			if( done ) {
				$items.eq(cur).before($items.eq(next));
				$pane.scrollTo($items[cur]);
			}
			done = false;
			pause = false;
			switch (ele.data.direction) {
			case 'horizontal':
				speed = Math.abs((ele.data.duration - ele.data.velocity)/itemWidth * ($items.eq(next).offset().left - $pane.offset().left));
				break;
			case 'vertical':
				speed = Math.abs((ele.data.duration - ele.data.velocity)/itemHeight * ($items.eq(next).offset().top - $pane.offset().top));
				break;
			default:
			}
			$pane.scrollTo( $items[next], {
				duration: speed,
				easing: 'linear',
				onAfter: function() {
					cur = next;
					done = true;
					if( ele.data.timeout ) {
						ele.t1 = setTimeout(function(){
							scrollPrev();
						}, ele.data.timeout);
					} else {
						scrollPrev();
					}
				}
			});
		}

	}); // End of elements
};

})(jQuery);

