(function($) {
  $.fn.showcase = function(method) {
    /* plugin's default options */
    var defaults = {
        animate: true,
        fadeDuration: 600,
        showDuration: 12000,
        roundButtons: '.showcase-buttons li a',
        prevButton: '.button-showcase-left',
        nextButton: '.button-showcase-right',
        showcaseContent: '.showcase-content',
        showCaseInner: '.showcase-inner'
    };

    /* this will hold the merged default and user-provided properties
       you will have to access the plugin's properties through this object!
       settings.propertyName */
    var settings = { };

    /* public methods */
    var methods = {
      init : function(options) {
        return this.each(function() {
          settings = $.extend({}, defaults, options);
          var element = $(this);
          
          settings.fadeDuration = settings.fadeDuration;
          settings.showDuration = settings.showDuration;
          settings.stopOnOver = settings.stopOnOver;
          settings.roundButtons = $(settings.roundButtons);
          settings.prevButton = $(settings.prevButton);
          settings.nextButton = $(settings.nextButton);
          settings.showcaseContent = $(settings.showcaseContent);
         
          
          settings.numElements = settings.showcaseContent.length;
          settings.elementIndex = 0;
          settings.timeout = null;
          
          settings.currentButton =  $(settings.roundButtons[settings.elementIndex]);
          settings.currentButton.addClass('active');
          
          settings.currentContent = $(settings.showcaseContent[settings.elementIndex]);
          settings.currentContent.css('display', 'block');
          
          settings.prevButton.bind('click', function() {
            if(settings.animate) settings.animate = false;
            settings.currentContent.stop(true, true).fadeOut(settings.fadeDuration, function() {
              var i = helpers.previous();
              helpers.animateToIndex(i);
            });
          });
          
          settings.nextButton.bind('click', function() {
            if(settings.animate) settings.animate = false;
            settings.currentContent.stop(true, true).fadeOut(settings.fadeDuration, function() {
              var i = helpers.next();
              helpers.animateToIndex(i);
            });
            
          });
          
          settings.roundButtons.bind('click', function(e) {
            helpers.stop();
            var e = e || window.event;
            var t = e.target || e.scrElement;
            var i = t.id.replace('showcase-button-', '');
            
            var j = parseInt(i) - 1;
            helpers.animateToIndex(j);
          });
          
          element.bind('mouseover', function(e) {
            settings.animate = false;
            settings.currentContent.stop(true, true);
          });
          
          element.bind('mouseout', function(e) {
            settings.animate = true;
            settings.currentContent.stop(true, true);
            helpers.animateToNext();
          });
          
          try {
            settings.timeout = setTimeout(helpers.start(), settings.showDuration);
          } catch(e) { }
        });
      }
    };
    
    /** private methods
     *  these methods can be called only from within the plugin
     * private methods can be called as
     * helpers.methodName(arg1, arg2, ... argn) */
    var helpers = {
      currentButton: function() {
        settings.currentButton = $(settings.roundButtons[settings.elementIndex]);
        return settings.currentButton;
      },
      
      currentContent: function() {
        settings.currentContent = $(settings.showcaseContent[settings.elementIndex]);
        return settings.currentContent;
      },
      
      next: function() {
        (settings.elementIndex >= settings.numElements - 1) ? settings.elementIndex = 0 :  settings.elementIndex++;
        return settings.elementIndex;
      },
      
      previous: function() {
        (settings.elementIndex > 0) ? settings.elementIndex-- :  settings.elementIndex = settings.numElements - 1;
        return settings.elementIndex;
      },
      
      animateToNext: function() {
        settings.currentContent.delay(settings.showDuration).fadeOut(settings.fadeDuration, function() {
          if(!settings.animate) return;
          
          helpers.next();
          settings.currentContent = helpers.currentContent();
          settings.roundButtons.removeClass('active');
          settings.currentButton = helpers.currentButton();
          settings.currentButton.addClass('active');

          settings.currentContent.fadeIn(settings.fadeDuration, function() {
            if(settings.animate) {
              helpers.animateToNext();
            }
          });
        });
      },
      
      animateToPrevious: function() {
        settings.currentContent.fadeOut(settings.fadeDuration, function() {
          if(!settings.animate) return;
          
          helpers.previous();
          settings.currentContent = helpers.currentContent();
          settings.roundButtons.removeClass('active');
          settings.currentButton = helpers.currentButton();
          settings.currentButton.addClass('active');
          
          settings.currentContent.fadeIn(settings);
        });
      },
      
      animateToIndex: function(index) {
        settings.currentContent.fadeOut(settings.fadeDuration, function() {
          settings.elementIndex = index;
          settings.currentContent = helpers.currentContent();
          settings.roundButtons.removeClass('active');
          settings.currentButton = helpers.currentButton();
          settings.currentButton.addClass('active');
          
          settings.currentContent.fadeIn(settings.fadeDuration);
        });
      },
      
      start: function() {
        settings.animate = true;
        helpers.animateToNext();
      },
      
      stop: function() {
        settings.animate = false;
        clearTimeout(settings.timeout);
      }
    };
    
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error( 'Method "' +  method + '" does not exist in pluginName plugin!');
    }
  }
})(jQuery);
