/*!
 * jQuery.Slider3D
 *
 * @projectDescription Slider3D for project krusnoman.com 
 * @author Jiri Prokop
 * @version 0.1
 *
 * @id jQuery.slider3d
 * @id jQuery.fn.slider3d
 * @param {Object} settings Hash of settings; objectSelectors, infoSelector, displaySelector, nextButtonSelector, prevButtonSelector are required.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 */

(function($) {
  var Slider3d = function(element, options) {
    // private fields and shortcuts
    var $elem = $(element);
    var me = this;
    var settings = $.extend({
      distance: 3000,
      objectSelectors: [],
      infoSelector: null,
      displaySelector: null,
      prevButtonSelector: null,
      nextButtonSelector: null
    }, options || {});
    var banners;
    var containerWidth;
    var containerHeight;
    var activeIndex = 0;
    var lastIndex;
    var animationFinished = true;
    var nextButtonizer;
    var prevButtonizer;
    
    //this.activeIndex = true;
    
    // private methods
    var initialize = function() {
      var $banners = $elem.find('.banner3d');
      $elem.empty();
      // just a little hack for refresh/back/forward correct functionality
      $elem.scrollTo(0, 750, {
        axis: 'x',
        queue: true
      });
      
      containerWidth = parseInt($elem.width());
      containerHeight = parseInt($elem.height());
      
      banners = [];
      lastIndex = ($banners.length - 1);
      $banners.each(function(index) {
        var objectSelectors = settings.objectSelectors;
        // adds info selector from object selects because of setting of common properties
        var $objects = $(this).find(objectSelectors.join(',') + ',' + settings.infoSelector);
        var widthBanner = parseInt($(this).width());
        var marginLeft = -(widthBanner / 2) + (index * settings.distance);
        
        $objects.css('position', 'absolute');
        $objects.css('left', '50%');
        $objects.css('margin-left', marginLeft);
        
        var $info = $(this).find(settings.infoSelector);
        var $display = $info.find(settings.displaySelector);
        var countdown = null;
        if ($display != null && $display.length != 0) {
          $display.countdown();
          countdown = $display.data('countdown');
        }
        banners[index] = {
          info: $info,
          countdown: countdown,
          objects3d: $(this).find(objectSelectors.join(',')),
          left: marginLeft
        };
        
        if (index != activeIndex) {
          $info.hide();
          var countdown = banners[index].countdown;
          if (countdown != null) {
            countdown.stop();
          }
        }
        
        $elem.append($objects);
      });
      
      var $terminator = $('<div>').css({
        position: 'absolute',
        left: ((settings.distance * $banners.length) - 1),
        width: '1',
        height: containerHeight
      });
      $elem.append($terminator);
      
      $('body').mousemove(function(e) {
        var offset = $elem.offset();
        var x = (e.pageX - offset.left);
        var y = (e.pageY - offset.top);
        var centerX = containerWidth / 2;
        var centerY = containerHeight / 2;
        effectKoefX = restrictKoef((x - centerX) / centerX);
        effectKoefY = restrictKoef((y - centerY) / centerY);
              
        moveActive3d(effectKoefX, effectKoefY);
      });
      
      var $next = $(settings.nextButtonSelector);
      nextButtonizer = $next.data('buttonizer');
      $next.click(function() {
        if (activeIndex < lastIndex && animationFinished) {
          var banner = banners[activeIndex];
          var info = banner.info;
          var countdown = banner.countdown;
          var nextBanner = null;
          var nextInfo = null;
          var nextCountdown = null;
          var $nextObjects = null;
          
          if ((activeIndex + 1) <= lastIndex) {
            nextBanner = banners[activeIndex + 1];
            nextInfo = nextBanner.info;
            nextCountdown = nextBanner.countdown;
            $nextObjects = nextBanner.objects3d;
          }
          
          animationFinished = false;
          // additional animation -->
          if (nextBanner != null) {
            var max = $nextObjects.length;
            $nextObjects.each(function(index) {
              var indexKoef = (max - (index + 1)) / max;
              var maxLeft = 50 + (50 * indexKoef);
              $(this).animate({
                left: (maxLeft + '%')
              }, 700).animate({
                left: '50%'
              }, 500);
            });
          }
          // <-- additional animation
          info.fadeOut(250, 'easeOutCubic', function() {
            if (countdown != null) {
              countdown.stop();
            }
            $elem.delay(200).scrollTo('+=' + settings.distance + 'px', 750, {
              axis: 'x',
              easing: 'easeOutBack',
              queue: true,
              onAfter: function() {
                if (nextBanner != null) {
                  if (nextCountdown != null) {
                    nextCountdown.start();
                  }
                  nextInfo.fadeIn(250, 'easeInCubic');
                }
                animationFinished = true;
              }
            });
          });
          
          activeIndex++;
          if (activeIndex == lastIndex) {
            nextButtonizer.disable();
          }
          prevButtonizer.enable();
        }
        return false;
      });
      
      var $prev = $(settings.prevButtonSelector);
      prevButtonizer = $prev.data('buttonizer');
      $prev.click(function() {
        if (activeIndex > 0 && animationFinished) {
          var banner = banners[activeIndex];
          var info = banner.info;
          var countdown = banner.countdown;
          var $objects = banner.objects3d;
          var prevBanner = null;
          var prevInfo = null;
          var prevCountdown = null;
          
          if ((activeIndex - 1) >= 0) {
            prevBanner = banners[activeIndex - 1];
            prevInfo = prevBanner.info;
            prevCountdown = prevBanner.countdown;
          }
          
          animationFinished = false;
          // additional animation -->
          var max = $objects.length;
          $objects.each(function(index) {
            var indexKoef = (index + 1) / max;
            var maxLeft = 60 + (30 * indexKoef);
            $(this).animate({
              left: (maxLeft + '%')
            }, 700).animate({
              left: '50%'
            }, 500);
          });
          // <-- additional animation
          info.fadeOut(250, 'easeOutCubic', function() {
            if (countdown != null) {
              countdown.stop();
            }
            $elem.delay(200).scrollTo('-=' + settings.distance + 'px', 750, {
              axis: 'x',
              easing: 'easeInBack',
              queue: true,
              onAfter: function() {
                if (prevBanner != null) {
                  if (prevCountdown != null) {
                    prevCountdown.start();
                  }
                  prevInfo.fadeIn(250, 'easeInCubic');
                }
                animationFinished = true;
              }
            });
          });
          
          activeIndex--;
          if (activeIndex == 0) {
            prevButtonizer.disable();
          }
          nextButtonizer.enable();
        }
        return false;
      });
      
      prevButtonizer.disable();
    };
    
    var restrictKoef = function(koef) {
      if (koef > 1) {
        return 1;
      } else if (koef < -1) { 
        return -1;
      } else {
        return koef;
      }
    };
    
    var moveActive3d = function(koefX, koefY) {
      move3d(activeIndex, koefX, koefY);
    }
    
    var move3d = function(index, koefX, koefY) {
      var banner = banners[index];
      var $objects = banner.objects3d;
      var left = banner.left;
      var addKoefX = 5; 
      
      var max = $objects.length;
      $objects.each(function(index) {
        var indexKoef = (index + 1) / max;
        $(this).css({
          marginTop: koefY * 15 * indexKoef,
          marginLeft: left + (koefX * addKoefX * 15 * indexKoef)
        });
      });
    };
    
    // initialize
    initialize();
  };

  $.fn.slider3d = function(options) {
    return this.each(function() {
      var $elem = $(this);
      var key = 'slider3d';
      var data = $elem.data(key);
      var instanceExists = false;
      
      if (typeof data !== 'undefined' && data instanceof Slider3d) {
        instanceExists = true;
      } else if (typeof data === 'object') {
        // options from html data-element are merged together with options of plugin when initializing
        options = $.extend(data, options || {});
      }
      
      if (!instanceExists) {
        $elem.data(key, new Slider3d(this, options));
      }
    });
  };
})(jQuery);
