;(function($){
    
    
    // jQuery plugin
    $.fn.techtwoCaroussel = function(options) 
    {
        return this.each(function(){
            
            /**
             * Internal mapping to this
             * @var techtwoCaroussel
            */
            var caroussel           = this;
            
            /**
             * Html element
             * @var jQuery
            */
            caroussel.wrapper       = $(this);
            
            /**
             * Caroussel configuration settings
             * @var object
            */
            caroussel.settings      = $.extend({}, $.fn.techtwoCaroussel.defaults, options);
            
            /**
             * Panels (frames) to animate
             * @var array
            */
            caroussel.panels        = caroussel.wrapper.find(caroussel.settings.panelSelector);
            
            /**
             * Counter for the current active panel
             * @var int
            */
            caroussel.activePanel   = 0;
            
            /**
             * Is hovered
             * @var boolean
            */
            caroussel.hover         = false;
            
            /**
             * Load animation and controls
             * @param none
             * @return void
            */
            caroussel.initialize = function()
            {
                // Check animation availability
                if (!$.fn.techtwoCaroussel.animations[caroussel.settings.animation]) {
                    alert('undefined animation ' + caroussel.settings.animation);
                    return;
                }
                
                
                // Initialize animation
                caroussel.animation = $.fn.techtwoCaroussel.animations[caroussel.settings.animation](caroussel.settings.animationOptions, caroussel);
                
                // Do we need to load controls?
                if (caroussel.settings.controls) {
                    
                    // Check controls availability
                    if (!$.fn.techtwoCaroussel.controls[caroussel.settings.controls]) {
                        alert('undefined animation ' + caroussel.settings.controls);
                        return;
                    }
                    
                    // Initialize controls
                    caroussel.controls = $.fn.techtwoCaroussel.controls[caroussel.settings.controls](caroussel.settings.controlOptions, caroussel);
                }
                
                // Start autoplay ?
                if (caroussel.settings.autoPlay) {
                    caroussel.initAutoPlay();
                }
                
                // Toggle hover
                caroussel.wrapper.hover(function(){
                    caroussel.hover = true;
                }, function(){
                    caroussel.hover = false;
                });
                
                caroussel.wrapper.data('caroussel', caroussel);
            };
            
            /**
             * Go forward 1 panel
             * @param none
             * @return void
            */
            caroussel.next = function()
            {
                var next = caroussel.getNextPanel();
                caroussel.gotoPanel(next);
                caroussel.activePanel = next;
            };
            
            /**
             * Go back 1 panel
             * @param none
             * @return void
            */
            caroussel.back = function()
            {
                caroussel.gotoPanel(caroussel.getPreviousPanel());
            };
            
            /**
             * Alias for back()
             * @param none
             * @return void
            */
            caroussel.forward = function()
            {
                caroussel.next();
            };
            
            /**
             * Alias for next()
             * @param none
             * @return void
            */
            caroussel.previous = function()
            {
                caroussel.back();
            };
                        
            /**
             * Go to a specific panel
             * @param int index
             * @return void
            */
            caroussel.gotoPanel = function (index)
            {
                // Trigger animation
                caroussel.animation.gotoPanel(index);

                caroussel.settings.onBeforeAnimate(index);
                
                // If nessecary, trigger controls
                if (caroussel.controls) {
                    caroussel.controls.gotoPanel(index);
                }
                
                if (caroussel.timer) {
                    caroussel.initAutoPlay();
                }
                
                caroussel.settings.onAfterAnimate(index);
                
            };
            
            /**
             * Retrieve animation class
             * @param none
             * @return void
            */
            caroussel.getAnimation = function()
            {
                return caroussel.animation;
            };
            
            /**
             * Utility method to get the previous panel index
             * @param none
             * @return int
            */
            caroussel.getPreviousPanel = function()
            {
                return (0 > (caroussel.activePanel - 1) ? (caroussel.panels.length - 1) : caroussel.activePanel - 1);
            };
               
            /**
             * Utility method to get the next panel index
             * @param none
             * @return int
            */   
            caroussel.getNextPanel = function () 
            {
                return (caroussel.panels.length <= (caroussel.activePanel + 1) ? 0 : caroussel.activePanel + 1);
            };
            
            /**
             * Initialize autoplay
             * @param none
             * @return void
            */   
            caroussel.initAutoPlay = function()
            {
                caroussel.settings.autoPlay = true;
                caroussel.timer = window.setTimeout(caroussel.autoPlay, caroussel.settings.delay);
            };
            
            /**
             * Autoplay function
             * @param none
             * @return void
            */   
            caroussel.autoPlay = function()
            {
                if (caroussel.timer) {
                    window.clearTimeout(caroussel.timer);
                }
                
                if (!caroussel.settings.autoPlay) {
                    return;
                }
                
                if (!caroussel.settings.pauseOnHover || !caroussel.hover) {
                    caroussel.next();
                }
                       
                caroussel.timer = setTimeout(caroussel.autoPlay, caroussel.settings.delay);
            };            
                        
            caroussel.initialize();
            
        });
    };
    
    // Wrapper for animations
    $.fn.techtwoCaroussel.animations = {};

    // Wrapper for controls
    $.fn.techtwoCaroussel.controls = {};
        
    // Default settings
    $.fn.techtwoCaroussel.defaults = {
        
        // Elements
        panelSelector: '>li',
        
        // Controlls
        pauseOnHover: false,
        controls: false,
        controlOptions: {},
        
        // Animation
        autoPlay: true,
        delay: 3000,
        duration: 400,
        animation: 'fade',
        animationOptions: {},
        onBeforeAnimate: function(){},
        onAfterAnimate: function(){}
    };
  
})(jQuery);
