(function($){
	
	var SliderWithPreview = function( element, options )
	{
		var elem 	= $(element);
		var obj 	= this;

		// Options
		// ----------------------------------------------------------
		
		var o = $.extend({
			nextItemPreviewWidth: 	126,
			itemsMargin: 			5,
			nextButtonUrl: 			'',
			intervalTime: 			5000,
			debug: 					false			
		}, options || {});


		// Variables
		// ----------------------------------------------------------
		
		var interval;
		
		var flagMoving 	= false;
		var flagHover	= false;
		
		var list 	= $('ul', elem);
		var items	= $('li', list);
		
		var wrapperHeight 	= parseFloat(elem.height());
		var wrapperWidth 	= parseFloat(elem.width());
		
		var itemWidth 		= wrapperWidth - o.itemsMargin - o.nextItemPreviewWidth;
		var moveStep		= itemWidth + o.itemsMargin;

		// Methods - PRIVATE
		// ----------------------------------------------------------
		
		var setupElements = function()
		{
			var clon1 	= items.eq(0).clone().appendTo(list).addClass('item-last');
			var clon2 	= items.eq(1).clone().appendTo(list);			
			items		= items.add(clon1).add(clon2);		
			
			var listStyle = {
				'height': 	wrapperHeight + 'px',
				'width': 	(itemWidth * items.size() + o.nextItemPreviewWidth)  + 'px'
			};
			
			var itemsStyle = {
				'height': 			wrapperHeight + 'px',
				'width': 			itemWidth + 'px',
				'margin-right': 	o.itemsMargin + 'px'
			};
			
			var wrapperStyle = {
				'height': 			wrapperHeight + 'px',
				'width': 			itemWidth + 'px'
			};
			
			list.css( listStyle );
			
			items
			.css(itemsStyle)
			.each(function(){
				
				var item = $(this);
				item.bind('mouseover mouseout', function(e){
					$(this).toggleClass('item-hover');
				})
				
				var link = $(this).find('a').css( wrapperStyle );
				
				
				if ( o.nextButtonUrl )		
					link.prepend('<img class="nextBtn" src="' + o.nextButtonUrl + '" />');
					
				link.prepend('<div class="cover"></div>').children( 'div.cover' ).css( wrapperStyle );
				
				link.bind('click', function(e){
					if ( !item.hasClass('item-active') )
					{
						if ( !flagMoving )
						{
							doScroll( item );
						}
						e.preventDefault();
					}
				});
				
			});
			
		}
		
		var doScroll = function( item )
		{
			var previous 	= item.prev();
			var isLast		= ( item.hasClass('item-last') ) ? true : false;
			
			flagMoving = true;
			
			item.addClass('item-active').find('.caption').fadeIn('fast');
			
			if ( isLast )
				items.eq(0).addClass('item-active').find('.caption').show();
			
			previous.find('.caption').fadeOut('fast');
				
			list.animate({ 'margin-left': '-=' + moveStep + 'px' }, 500, 'swing', function(){
				
				if ( isLast ){					
					list.css({ 'margin-left': 0 });
					item.removeClass('item-active').find('.caption').hide();
				}
				
				previous.removeClass('item-active');
								
				setTimeout(function(){
					flagMoving = false;
				}, 100);				
			});
		}
		
		var startInterval = function()
		{
			interval = setInterval(function(){
				var item = items.filter('.item-active').next();
				doScroll( item );				
			}, o.intervalTime);
		}
		
		var bindPause = function()
		{
			elem.bind('mouseover mouseout', function(e){
				if ( e.type=='mouseover' )
				{
					clearInterval( interval );
				}
				else if ( e.type=='mouseout' )
				{
					startInterval();
				}
			});
		}



		// Methods - PUBLIC
		// ----------------------------------------------------------
		
		this.getRequiredFields = function()
		{
			return $('['+o.validationAttr+']', elem);
		};



		// Main
		// ----------------------------------------------------------
		
		if ( list.size()>0 && items.size()>0 )
		{	
			setupElements();
			items.filter(':first').addClass('item-active').find('.caption').show();
			bindPause();
			startInterval();
		}
		else
		{
			alert('missing elements.')
		}
				
	};

	$.fn.SliderWithPreview = function( options )
	{		
		var element 		= $(this);
		var elementData 	= element.data('sliderwithpreview');
		
		if ( elementData ){
			return elementData;
		} else {
			var sliderwithpreview = new SliderWithPreview(this, options);
			element.data('sliderwithpreview', sliderwithpreview);			
			return sliderwithpreview;
		}		
	};

})(jQuery);
