var Carousel = (function() {
  var _all,                         // All the links in rotation
      _selected,                    // Index of currently "selected" link (featured)
      _timeout,                     // Timeout object of the carousel
      _faded_img_opacity = 0.15,    // Opacity of images when faded.
      _animation_duration = 650,    // Duration of slide
      _pre_rotation_duration = 300, // Duration of pre-slide animations (arrows, details, etc);
      _delay = 15000;               // Delay between rotations
  var _container = function() { return $('.carousel_slider'); };  
  
  var _next_link = function() { 
    var _offset = arguments[0] || 2;
    var _new= $(_all[(_selected+_all.length+_offset) % _all.length]).attr('class', '').addClass('new').show();
    _new.find('img').css('opacity', _faded_img_opacity);
    return _new;
  };
  
  var _prev_link = function() { 
    var _new = _next_link(-2); 
    return _new;
  };
  
  var _beforeRotation = function(callback) {
    clearTimeout(_timeout);
    _container().find('a').unbind();
    $('.project_details:visible').fadeOut(_pre_rotation_duration);
    $('.arrow').fadeOut(_pre_rotation_duration);
    if (callback) { setTimeout(callback, _pre_rotation_duration); }
  };
  
  var _afterRotation = function() {
    $('.project_'+_selected).fadeIn(_pre_rotation_duration);
    $('.arrow').fadeIn(_pre_rotation_duration);
    if (_carousel_opts.autorotate) {
      Carousel.timeoutFunction();
    }
  };
  
  return {    
    next: function() {
      _beforeRotation();
      var _new = _next_link(),
          _old_left = _container().css('left'),
          _new_left = (parseInt(_old_left) - _carousel_opts.slideDistance) + 'px';
      _container().append(_new);
      _container().find('a.selected img').animate({opacity: _faded_img_opacity}, _animation_duration);
      _container().find('a.next img').animate({opacity: 1}, _animation_duration);      
      _container().animate({left: _new_left}, _animation_duration, function() {
        var _c = $(this);
        _c.find('a.previous').remove();
        _c.find('a.selected').switchClass('selected', 'previous')
        .find('img').css('opacity', _faded_img_opacity);
        _c.find('a.next').switchClass('next', 'selected')
        .find('img').css('opacity', 1);
        _c.find('a.new').switchClass('new', 'next')
        .find('img').css('opacity', _faded_img_opacity);
        _c.css('left', _old_left);
        _new.one('mousemove', function() { $('a.arrow.next').addClass('next_hover'); });        
        _selected = (_selected+1) % _all.length;
        _afterRotation();
      });
    },

    previous: function() {
      _beforeRotation();
      var _new = _prev_link(),
          _old_left = _container().css('left'),
          _new_left = (parseInt(_old_left) - _carousel_opts.slideDistance) + 'px';
      _container().css({left: _new_left})
                  .prepend(_new);
      _container().find('a.selected img').animate({opacity: _faded_img_opacity}, _animation_duration);
      _container().find('a.previous img').animate({opacity: 1}, _animation_duration);      
      _container().find('a.next').fadeOut(_animation_duration);
      _container().animate({left: _old_left}, _animation_duration, function() {
        var _c = $(this);
        _c.find('a.next').remove();
        _c.find('a.selected').switchClass('selected', 'next')
          .find('img').css('opacity', _faded_img_opacity);
        _c.find('a.previous').switchClass('previous', 'selected')
          .find('img').css('opacity', 1);
        _c.find('a.new').switchClass('new', 'previous')
          .find('img').css('opacity', _faded_img_opacity);
        _new.one('mousemove', function() { $('a.arrow.previous').addClass('previous_hover'); });          
        _selected = (_selected-1+_all.length) % _all.length;
        _afterRotation();
      });
    },

    timeoutFunction: function() {
      _timeout = setTimeout(function() {
        Carousel.next();
      }, _delay);
    },
    init: function(opts) {
      /**
       * Valid Options:
       * autorotate - boolean
       * slideDistance - integer number of pixels
       */
      _carousel_opts = opts || {};
      _all = _container().find('a');
      _all.filter(':gt(2)').remove();
      _container().find('a:eq(0)').addClass('previous')
        .find('img').css("opacity", _faded_img_opacity);
      _container().find('a:eq(1)').addClass('selected');
      _container().find('a:eq(2)').addClass('next')
        .find('img').css("opacity", _faded_img_opacity);
      
      _selected = 1;      
      $('.project_details').hide();
      $('.project_'+_selected).show();
      $('a.arrow.next').click(function() {Carousel.next(); return false;});
      $('a.arrow.previous').click(function() {Carousel.previous(); return false;});
      $('.carousel_slider a.next')
        .live('mouseenter', function() { $('a.arrow.next').addClass('next_hover'); })
        .live('mouseleave', function() { $('a.arrow.next').removeClass('next_hover'); })
        .live('mousedown', function() { $('a.arrow.next').addClass('next_active'); })
        .live('mouseup', function() { $('a.arrow.next').removeClass('next_active'); })
        .live('click', function() {Carousel.next(); return false;});

      $('.carousel_slider a.previous')
        .live('mouseenter', function() { $('a.arrow.previous').addClass('previous_hover'); })
        .live('mouseleave', function() { $('a.arrow.previous').removeClass('previous_hover'); })
        .live('mousedown', function() { $('a.arrow.previous').addClass('previous_active'); })
        .live('mouseup', function() { $('a.arrow.previous').removeClass('previous_active'); })
        .live('click', function() {Carousel.previous(); return false;});
      
      $('.carousel_slider a.new').live('click', function() { return false; });
      
      if (_carousel_opts.autorotate) {
        Carousel.timeoutFunction();
      }
    }
  };
})();
