(function($){
	$.fn.extend({ 
		infiniteCarousel: function(options) {
			var defaults = {
				transitionSpeed: 1000,
				displayTime: 1000,								
				displayThumbnails: true,								
				easeLeft: 'easeInOutExpo',
				easeRight: 'easeInOutExpo',				
				inView: 1,
				padding: 4,
				advance: 1,
				showControls: true,
				autoHideControls: false,				
				autoStart: true,
				sliderId: 'defaultId',
				onSlideStart: function(){},
				onSlideEnd: function(){},
				onPauseClick: function(){}
			};
			/* variables */
			var options = $.extend(defaults, options);	
    		return this.each(function() {
    		var isRuning = false;
			var o = options;
			var obj = $(this);
			var autopilot = o.autoStart;			
			var sID = ('_' + o.sliderId);
			var numImages = $('img', obj).length;
			var imgHeight = $('img:first', obj).height();
			var imgWidth = $('img:first', obj).width();
			var opacityValue = 1;			
			if($.browser.msie){
				opacityValue='';
			}
			if(o.inView > numImages-1) { o.inView = numImages-1; }
			var imgWidthShiftFrame = imgWidth*o.inView;
			var imgWidthShift = - imgWidth - o.padding*2;
			var imgWidthShiftFadeRight = - imgWidth - o.padding;
			
			$(obj).width(imgWidthShiftFrame).height(imgHeight);
			$(obj).parent().width(imgWidthShiftFrame).height(imgHeight);
			$('ul', obj).width(imgWidth*numImages);
			$('li:last', obj).prependTo($('ul', obj));
			$('ul', obj).css('left',imgWidthShift+'px').width(9999);

			var containerBorder = parseInt($(obj).css('border-bottom-width')) + parseInt($(obj).css('border-top-width'));
			if(isNaN(containerBorder)) containerBorder = 0; 
			var containerPaddingLeft = parseInt($(obj).css('padding-left'));
			if(o.displayThumbnails) {
				function thumbclick(event) {
					if (isRuning) {
						return;
					}
					var index = this.id.split('_')[3];
					if(viewable[0] != index) {
						status='pause';
						clearTimeout(clearInt);
						$('#thumbs'+sID+' div').unbind('click');
						autopilot = 0;
					}
					if(index > viewable[0]) {
						diff = index - viewable[0];
						moveLeftWithFade(diff);
					}
					if(index < viewable[0]) {
						diff = viewable[0]- index;
						moveRightWithFade(diff);
					}
				}

				var viewable = [];
				var unviewable = [];
				$(obj).after(create('div', 'thumbs' + sID, 'thumbs'));				
				for(i=0;i<=numImages-1;i++) {					
					$('#thumbs' + sID).append(create('div', 'thumb'+sID+'_'+(i+1), 'thumb').html(i+1));					
					if(i<=o.inView) $('#thumb'+sID+'_'+i).addClass('thumb_border'); 					
					unviewable.push(i+1);
				}
				for(i=1;i<=o.inView;i++) viewable.push(unviewable.shift());
				$('#thumbs'+sID+' div.thumb:not(:first)').css({opacity:.65});
				$('#thumbs'+sID+' div.thumb').hover(function(){$(this).css({opacity:1})},function(){if(viewable[0]!=this.id.split('_')[3]) $(this).css({opacity:.65})});
				$('#thumbs'+sID+' div').bind('click', thumbclick);
			}

			if(o.showControls) {
				arrowsTop = ((imgHeight/2)-15)+o.padding;				
				$(obj).append(create('div', 'btn_rt'+sID, 'btn_rt').html('&nbsp;').css('top', arrowsTop)).append(create('div', 'btn_lt'+sID, 'btn_lt').html('&nbsp;').css('top', arrowsTop));				
				$('#btn_rt'+sID).css('opacity',.5).click(function(){
					forcePrevNext('next');
				}).hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.5'},250)});
				$('#btn_lt'+sID).css('opacity',.5).click(function(){
					forcePrevNext('prev');
				}).hover(function(){$(this).animate({opacity:'1'},250)},function(){$(this).animate({opacity:'.5'},250)});

				if(o.autoHideControls) {
					function showcontrols() {
						$('#btn_rt'+sID).stop().animate({top:arrowsTop+'px',right:'2px'},250);
						$('#btn_lt'+sID).stop().animate({top:arrowsTop+'px',left:'2px'},250);
					}
					function hidecontrols() {
						$('#btn_rt'+sID).stop().animate({right:'-32px'},250);
						$('#btn_lt'+sID).stop().animate({left:'-32px'},250);
					}
					$(obj).hover(showcontrols,hidecontrols);
					hidecontrols();
				}
			}
			
			function create(elem, id, style) {
				var element = document.createElement(elem);
				return $(element).attr('id', id).addClass(style);				
			}

			function forcePrevNext(dir) {								
				$('#btn_rt' + sID).unbind('click');
				$('#btn_lt' + sID).unbind('click');
				autopilot = 0;				
				status = 'pause';
				clearTimeout(clearInt);
				(dir == 'prev') ? moveRight() : moveLeft();				
				setTimeout(function(){						
						$('#btn_rt'+sID).bind('click',function(){forcePrevNext('next')});
						$('#btn_lt'+sID).bind('click',function(){forcePrevNext('prev')});
				},o.transitionSpeed);
			}

			function preMove() {
				if(o.showControls) { $('#btn_lt'+sID).fadeOut(200); $('#btn_rt'+sID).fadeOut(200); }
				if(o.displayThumbnails) for(i=1;i<=numImages;i++) $('#thumb'+sID+'_'+i).removeAttr('style').css('opacity', .65);						
			}

			function postMove(){
				if(o.showControls) { $('#btn_lt'+sID).fadeIn(200); $('#btn_rt'+sID).fadeIn(200); }
				if(o.displayThumbnails) {
					for(i=0;i<=numImages-1;i++) $('#thumb'+sID+'_'+(i+1)).removeClass('thumb_border');
					$('#thumb'+sID+'_'+viewable[viewable.length-1]).addClass('thumb_border').animate({opacity: 1},500);
					$('#thumbs'+sID+' div').unbind('click').bind('click', thumbclick);
				}
				ary=[];
				for(x=1;x<=o.inView;x++){ary.push($('img:eq('+x+')',obj).attr('src'))}
				o.onSlideEnd.call(this,ary);
			}

			function moveLeft(dist) {
				isRuning = true;
				if(dist == null) dist = o.advance;				
				preMove();
				if(o.displayThumbnails) {
					for(i=1; i<=dist ;i++){
						viewable.push(unviewable.shift());
						unviewable.push(viewable.shift());
					}
				}
				if(o.displayTime == 0){clearInterval(clearInt);}
				$('li:lt('+dist+')', obj).clone(true).insertAfter($('li:last', obj));
				o.onSlideStart.call(this,viewable,'left');
				$('ul', obj).animate({left:imgWidthShift*(dist+1)+o.padding},o.transitionSpeed,o.easeLeft,function(){ 
					$('li:lt('+dist+')', obj).remove(); 
					$(this).css({'left':imgWidthShift});
					postMove();
					if(o.displayTime == 0){moveLeft();}
					isRuning = false;
				});
			}
			
			function moveLeftWithFade(dist) {
				isRuning = true;
				if(dist == null) dist=o.advance;
				preMove();
				if(o.displayThumbnails) {
					for(i=1;i<=dist;i++){
						viewable.push(unviewable.shift());
						unviewable.push(viewable.shift());
					}
				}
				if(o.displayTime == 0){clearInterval(clearInt);}
				$('li:lt('+dist+')', obj).clone(true).insertAfter($('li:last', obj));
				o.onSlideStart.call(this,viewable,'left');
				$('ul', obj).animate({opacity:.3},o.transitionSpeed/4,o.easeLeft,function(){
					$('li:lt('+dist+')', obj).remove();	
					$(this).css({'left':imgWidthShift});	
					$(this).animate({opacity:opacityValue},o.transitionSpeed/4);
					postMove();
					if(o.displayTime == 0){moveLeft();}
					isRuning = false;
				});						
			}
			
			function moveRight(dist) {
				isRuning = true;
				if(dist==null) dist=o.advance;
				preMove();
				if(o.displayThumbnails)
				{
					for(i=1;i<=dist;i++){
						viewable.unshift(unviewable.pop());
						unviewable.unshift(viewable.pop());
					}
				}
				$('li:gt('+(numImages-(dist+1))+')', obj).clone(true).insertBefore($('li:first', obj));
				o.onSlideStart.call(this,viewable,'right');
				$('ul', obj).css('left',imgWidthShiftFadeRight*(dist+1)-o.padding)
					.animate({left:imgWidthShift},o.transitionSpeed,o.easeRight,function(){
						$('li:gt('+(numImages-1)+')', obj).remove();
						postMove();
						isRuning = false;
					});
			}
			
			function moveRightWithFade(dist) {
				isRuning = true;
				if(dist==null) dist=o.advance;
				preMove();
				if(o.displayThumbnails) {
					for(i=1;i<=dist;i++){
						viewable.unshift(unviewable.pop());
						unviewable.unshift(viewable.pop());
					}
				}
				$('li:gt('+(numImages-(dist+1))+')', obj).clone(true).insertBefore($('li:first', obj));
				o.onSlideStart.call(this,viewable,'right');
				$('ul', obj).css('left',imgWidthShiftFadeRight*(dist+1)-o.padding)
					.animate({opacity:.3},o.transitionSpeed/4,o.easeRight,function(){				
						$('li:gt('+(numImages-1)+')', obj).remove();
						$(this).css('left', imgWidthShift);
						$(this).animate({opacity:opacityValue}, o.transitionSpeed/4);
						postMove();
						isRuning = false;
					});
			}
			if(autopilot) {
				var clearInt = setInterval(function(){moveLeft();},o.displayTime+o.transitionSpeed);
			} 
 		});
	}
	});
})(jQuery);
