(function($){
	$.jqImageCarousel = function(el, options, objectID)
	{
		var base = this;
		//Context Element
		base.contextEl = $(el); 
		
		base.contextEl.data('objectID', objectID);
		
		base.setEvents = function()
		{
			//Adicionar evento click previous
			$(base.options.directionElements.previous).bind('click', function(ev){
				ev.preventDefault();
				
				//Before callback
				base.options.beforePrev();
				
				var objAnim;
			
				if(base.animDirection == 'left')
				{
					objAnim = { left : '+=' + base.liMeasure };
				}
				else
				{
					objAnim = { top : '+=' + base.liMeasure };
				}
					
				//Animar o elemento
				$('ul:not(:animated)', base.contextEl).animate(objAnim, base.options.animSpeed, base.options.animEasing, function(){
					//Mover o último elemento para a primeira posição
					$('li:last', base.contextEl).insertBefore($('li:first', base.contextEl)); 
						
					//Colocar elemento correcto na sua posição correspondente
					$('ul', base.contextEl).css(base.animDirection, base.ulCssValue);
					
					//After callback
					base.options.afterPrev();
				});
			});
			
			//Adicionar evento click next
			$(base.options.directionElements.next).bind('click', function(ev){
				ev.preventDefault();
				
				//Before callback
				base.options.beforeNext();
				
				var objAnim;
				
				if(base.animDirection == 'left')
				{
					objAnim = { left : '-=' + base.liMeasure };
				}
				else
				{
					objAnim = { top : '-=' + base.liMeasure };
				}
				
				//Animar o elemento
				$('ul:not(:animated)', base.contextEl).animate(objAnim, base.options.animSpeed, base.options.animEasing, function(){
					//Mover o primeiro elemento para a última posição 
					$('li:first', base.contextEl).insertAfter($('li:last', base.contextEl));      
						
					//Colocar elemento correcto na sua posição correspondente
					$('ul', base.contextEl).css(base.animDirection, base.ulCssValue);
					
					//After callback
					base.options.afterNext();
				});
			});
			
			if (base.options.resizeEvent.setEvent && base.options.resizeEvent.handlerContextElm != '') {
				var resizeHandler;
	
				resizeHandler = function () {
					var objAnim, liStyle;
					base.ulCssValue = (base.liMeasure = $(base.options.resizeEvent.handlerContextElm).innerWidth()) * (-1);
					
					if (base.animDirection == 'left') {
						objAnim = { left : '-' + base.liMeasure + 'px' };
						liStyle = { width : base.liMeasure };
					} else {
						objAnim = { top : '-' + base.liMeasure + 'px' };
						liStyle = { height : base.liMeasure };
					}
					
					$('ul', base.contextEl)
						.css(objAnim)
						.find('li')
						.css(liStyle)
						.end();
				};
				
				$(window).resize(resizeHandler);
			}
		};
		
		base.initSetInterval = function()
		{
			base.autoRun = setInterval(function(){ base.autoRotationFunction(); }, base.options.timeInterval);
			
			//Eventos mouseover e mouseout
			if(base.options.stopOnHover)
			{
				$('ul', base.contextEl).bind({
					mouseover : function(){
						base.clearAutoSlide();
					},
					
					mouseout : function(){
						base.autoRun = setInterval(function(){ base.autoRotationFunction(); }, base.options.timeInterval);
					}
				});
			}
		};

		//Função usada no SetInterval
		base.autoRotationFunction = function()
		{
			//Before callback
			base.options.beforeNext();
			
			var objAnim;
			
			if(base.animDirection == 'left')
			{
				objAnim = { left : '-=' + base.liMeasure };
			}
			else
			{
				objAnim = { top : '-=' + base.liMeasure };
			}
			
			//Animar o elemento
			$('ul:not(:animated)', base.contextEl).animate(objAnim, base.options.animSpeed, base.options.animEasing, function(){
				//Mover o primeiro elemento para a última posição 
				$('li:first', base.contextEl).insertAfter($('li:last', base.contextEl));
					
				//Colocar elemento correcto na sua posição correspondente
				$('ul', base.contextEl).css(base.animDirection, base.ulCssValue);
				
				//After callback
				base.options.afterNext();
			});
		};
		
		//API Method (Argument zero-based)
		base.slideTo = function(slideNum)
		{
			if(typeof(slideNum) == 'number')
			{
				if($('ul', base.contextEl).is(':not(:animated)'))
				{
					//Before callback
					base.options.beforePrev();
					
					var objAnim, currentIndex, animValue = 0;
					
					currentIndex = $('li[initialPosition='+slideNum+']').index();
					animValue = ((currentIndex - 1) * base.ulCssValue);

					if(base.animDirection == 'left')
					{
						objAnim = { left : '+=' + animValue };
					}
					else
					{
						objAnim = { top : '+=' + animValue };
					}
					
					$('ul', base.contextEl).animate(objAnim, base.options.animSpeed, base.options.animEasing, function(){
						$('li', $(this)).slice(0, currentIndex - 1).each(function(){
							$(this).insertAfter($('li:last', base.contextEl)); 
						});
						
						$('ul', base.contextEl).css(base.animDirection, base.ulCssValue);
						
						//After callback
						base.options.afterPrev();
					});	
				}
			}
		};
		
		function init()
		{
			base.options = $.extend($.jqImageCarousel.defaultOptions, options);
			
			//Calcular o tamanho de cada item e o valor a passar à ul
			if(base.options.direction == 'horizontal')
			{
				base.liMeasure = $('li:last', base.contextEl).outerWidth(true);
				
				if (base.contextEl.is('.holderSliderImages')) {
					base.liMeasure = base.contextEl.width();
				}
				
				base.animDirection = 'left';
			}
			else
			{
				base.liMeasure = $('li:last', base.contextEl).outerHeight(true);
				base.animDirection = 'top';
			}
			
			base.ulCssValue = base.liMeasure * (-1); 
			
			//Mover o último elemento para a primeira posição
			$('li:last', base.contextEl).insertBefore($('li:first', base.contextEl)); 
			
			//Colocar elemento correcto na sua posição correspondente
			//$('ul', base.contextEl).css(base.animDirection, base.ulCssValue);
			var objAnim;
			if(base.animDirection == 'left')
			{
				objAnim = { left : '-=' + base.liMeasure };
			}
			else
			{
				objAnim = { top : '-=' + base.liMeasure };
			}
			
			$('ul', base.contextEl).css('left', base.ulCssValue);
			
			base.setEvents();
			
			if(base.options.autoRotation)
			{
				base.initSetInterval();
			}
		};
		
		init();
	};
	
	$.jqImageCarousel.defaultOptions = {
		direction : 'horizontal',
		animSpeed : 500,
		animEasing : 'swing',
		directionElements : { previous : '.prevarrow', next : '.nextarrow' },
		timeInterval : 5000,
		autoRotation : true,
		stopOnHover : false,
		resizeEvent : {
			setEvent : false,
			handlerContextElm : ''
		},
		beforePrev : function () {}, //callback invoked before start animation
		afterPrev : function () {}, //callback invoked after start animation
		beforeNext : function () {}, //callback invoked before start animation
		afterNext : function () {} //callback invoked after start animation
	};
	
	//Holds currently ID
	$.jqImageCarousel.ObjectID = -1;
	//Array of objects
	$.jqImageCarousel.Objects = [];
	
	$.fn.jqImageCarousel = function(options)
	{
		return this.each(function(){
			if(typeof(options) == 'number')
			{
				$.jqImageCarousel.Objects[$(this).data('objectID')].slideTo(options);
			}
			else
			{
				$.jqImageCarousel.ObjectID++;
				$.jqImageCarousel.Objects[$.jqImageCarousel.ObjectID] = new $.jqImageCarousel(this, options, $.jqImageCarousel.ObjectID);
			}
		});
	};
})(jQuery);
