(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.before();
                
                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.after();
                });
            });
            
            //Adicionar evento click next
            $(base.options.directionElements.next).bind('click', function(ev){
                ev.preventDefault();
                
                //Before callback
                base.options.before();
                
                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.after();
                });
            });
        };
        
        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(){
                        clearInterval(base.autoRun);
                    },
                    
                    mouseout : function(){
                        base.autoRun = setInterval(function(){ base.autoRotationFunction(); }, base.options.timeInterval);
                    }
                });
            }
        };

        //Função usada no SetInterval
        base.autoRotationFunction = function()
        {
            //Before callback
            base.options.before();
            
            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.after();
            });
        };
        
        //API Method (Argument zero-based)
        base.slideTo = function(slideNum)
        {
            if(typeof(slideNum) == 'number')
            {
                
                if($('ul', base.contextEl).is(':not(:animated)'))
                {
                    //Before callback
                    base.options.before();
                    
                    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.after();
                    }); 
                }
            }
        };
        
        base.init = function()
        {
            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:first', base.contextEl).outerWidth(true);
                base.animDirection = 'left';
            }
            else
            {
                base.liMeasure = $('li:first', 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).animate(objAnim, base.options.animSpeed, base.options.animEasing, function(){
                //After callback
                base.options.after();
            });
            
            base.setEvents();
            
            if(base.options.autoRotation)
            {
                base.initSetInterval();
            }
        };
        
        base.init();
    };
    
    $.jqImageCarousel.defaultOptions = {
        direction : 'horizontal',
        animSpeed : 0,
        animEasing : 'bounce',
        directionElements : { previous : '.prevarrow', next : '.nextarrow' },
        timeInterval : 5000,
        autoRotation : true,
        stopOnHover : false,
        before : function(){}, //callback invoked before start animation
        after : 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);
