jQuery.fn.carousel = function(carouselDefaults) {
  var carouselDefaults = jQuery.extend({
    show: 2,
    speed: 300,
    items: '.item',
    showControls: true,
    showPageControls: false,
    circle: false
  }, carouselDefaults);

  return this.each(function() {
    var carousel = $(this);

    // Wrap items in two DIVs
    carousel.wrapInner('<div class="carousel_list"></div>');
    carousel.wrapInner('<div class="carousel_wrapper"></div>');
    var carousel_wrapper = carousel.find('.carousel_wrapper');
    var carousel_list = carousel.find('.carousel_list');

    var carousel_items = carousel_list.find(carouselDefaults.items);
    var offset = 0;
    var active_page = 1;
    var number_of_pages = Math.ceil(carousel_items.length/carouselDefaults.show);
    var item_width = carousel_items.outerWidth(true);
    var item_height = carousel_items.outerHeight(true);


    // Set visible height of wrapper
    carousel_wrapper.height(item_height+'px');

    // Set actual width of list
    carousel_list.width(carousel_items.length*item_width);
    carousel_list.css({position: 'absolute', left: '0px'});

    // Remove bottom margin on items and set min_height.
    carousel_items.css({marginBottom: '0px'});
        
    // Set up the previous/next links
    var next_link = $('<a href="#">Next</a>')
    var previous_link = $('<a href="#">Previous</a>')
    next_link.click(next);
    previous_link.click(previous);
    next_li = $('<li class="next"></li>').append(next_link);
    previous_li = $('<li class="previous"></li>').append(previous_link);
    // Mark previous/next as inactive if there are no more pages.
    // But only do it if we aren't allowing circular carousels.
    if (!carouselDefaults.circle) { 
      carousel.bind('carousel:activate_page', function(e, page) {
        next_li.removeClass('inactive');
        previous_li.removeClass('inactive');
        if (page >= number_of_pages) { next_li.addClass('inactive') };
        if (page <= 1) { previous_li.addClass('inactive') };
      });      
    };

    // Insert controls
    if (carouselDefaults.showControls) {
      tabs = $('<ul class="carousel_tabs"></ul>');
      tabs.append(previous_li);
      tabs.append(next_li);
      carousel.append(tabs);

      // Create links for the individual pages if enabled
      if (carouselDefaults.showPageControls) {
        pages = $('<ul></ul>')
        for (iter=1;iter<=number_of_pages;iter++) {
          link = $('<a href="#"></a>').text(iter);
          link.click(function(e) {
            e.preventDefault();
            page_number = Number($(this).text())
            carousel.trigger('carousel:activate_page', [page_number]);
          });
          pages.append($('<li></li>').append(link));
        }
        // Stick the pages UL in it's own LI between the previous/next links
        previous_li.after($('<li class="pages"></li>').append(pages));
        // If we have page links bind them to the activate page event.
        carousel.bind('carousel:activate_page', function(e, page) {
          carousel.find('li.pages li').removeClass('active')
            .each(function() {
              if (page == Number($(this).text())) { 
                $(this).addClass('active'); 
              }
            });
        });
      }      
    };
    
    // Setup events and activate the initial page
    carousel.bind('carousel:activate_page', goToPage)
    carousel.bind('carousel:next', next)
    carousel.bind('carousel:previous', previous)
    carousel.trigger('carousel:activate_page', [active_page]);


    function next(e) {
      e.preventDefault();
      if ((active_page + 1) <= number_of_pages) {
        carousel.trigger('carousel:activate_page', [active_page + 1]);
      } else {
        if (carouselDefaults.circle) { 
          console.log("go to beginning");
          carousel.trigger('carousel:activate_page', [1]);
        } else {
          carousel_list.animate({left: '-=50px'}, 100).animate({left: '+=50px'}, 200)          
        }
      }  
    }

    function previous(e) {
      e.preventDefault();
      if (active_page > 1) {
        carousel.trigger('carousel:activate_page', [active_page - 1]);
      } else {
        if (carouselDefaults.circle) { 
          carousel.trigger('carousel:activate_page', [number_of_pages]);
        } else {        
          carousel_list.animate({left: '+=50px'}, 100).animate({left: '-=50px'}, 200)
        }
      }  
    }    

    function goToPage(e, page) {
      if (page > number_of_pages) { page = number_of_pages };
      if (page <= 0) { page = 1 };
      active_page = page;
      offset = (page * carouselDefaults.show) - carouselDefaults.show;
      move_to = offset * item_width;
      carousel_list.animate({left: -move_to+'px'}, carouselDefaults.speed); 
    }
  });
}
