( function($) {
  $.fn.isleCarousel = function(settings) {
  
    var timeoutVar = null;
    var that = null;
    var size = 0;
    var current = 0;
    var prependCount = 0;
    var origHeight;
    var origWidth;
    
    var config = {
      prevButtonSelector: '#caroPrev',
      nextButtonSelector: '#caroNext',
      captionTargetSelector: '#caroCaption',
      captionAttribute: 'alt',
      autoRotate: false,
      timeoutInterval: 2000,
      noToShow: 3,
      onChangeCallback: null,
      reductionMultiplier: 0.7
    }
    
    if (settings) {
			$.extend(config, settings);
		}
    
    function isNullOrNothing(o) {
      return typeof(o) === 'nothing' || o == null;
    }
    
    function showText(imgTag) {
      var text = $(imgTag).attr(config.captionAttribute);
      $(config.captionTargetSelector).text(text);
    }
    
    function tryChange(modifier) {
      var test = current + modifier;
      if (test >= prependCount && test < (size + prependCount)) {
        current = test;
        return true;
      }
      return false;
    }
    
    function tryRunCallback(callback) {
      if (typeof(callback) == 'function') {
        callback();
      }
    }
    
    function nextButtonClicked(forced) {
      if (tryChange(1)) {
        runAnim();
        tryRunCallback(config.onChangeCallback);
      }
      clearTimeout(timeoutVar);
      if (forced === true) {
        refreshTimeout();
      }
      return false;
    }
    
    function prevButtonClicked() {
      if (tryChange(-1)) {
        runAnim();
        tryRunCallback(config.onChangeCallback);
      }
      clearTimeout(timeoutVar);
      return false;
    }
    
    function showText(imgTag) {
			var text = $(imgTag).attr(config.captionAttribute);
			$(config.captionTargetSelector).text(text);
		}
    
    function initialize() {
      if ((config.noToShow % 2) != 0) {
        var ul = that.children('ul');
        var lis = that.children('ul').children('li');
        size = lis.size();
        
        if (size > 0) {
          $(config.nextButtonSelector).click(nextButtonClicked);
          $(config.prevButtonSelector).click(prevButtonClicked);
          
          ul.css('overflow', 'hidden');
          lis.css('float', 'left');
          
          prependCount = Math.floor(config.noToShow / 2);
          
          var j = 1;
          for (var i = 0; i < prependCount; i++, j++) {
            ul.prepend('<li style="float: left;"></li>');
          }
          
          lis = that.children('ul').children('li');
          
          current = prependCount;
          
          origHeight = $(lis[current]).children('a').children('img').attr('height');
          origWidth = $(lis[current]).children('a').children('img').attr('width');
          runAnim();
        }
      } else {
        alert('The setting "noToShow" must be an odd number');
      }
    }
    
    function runAnim() {
      var lis = that.children('ul').children('li');
      var upper = current + prependCount;
      var lower = current - prependCount;
      
      lis.each( function(i, val) {
        if (i < lower || i > upper) {
          $(val).hide('fast', function() {
            $(this).css({
              height: 0,
              width: 0
            });
          });
        } else if (i == current) {
          $(val).attr('class', 'foreground');
          showText($(val).children('a').children('img'));
        } else {
          $(val).show('fast');
        }
      });
      
      var currentLi = $(lis[current]);
      var currentA = currentLi.children('a');
      var currentImg = currentA.children('img');
      
      currentLi.animate({
        width: origWidth,
        height: origHeight,
        opacity: 1
      });
      currentImg.animate({
        width: origWidth,
        height: origHeight,
        opacity: 1
      });
      
      var i = 1;
      var tempWidth = origWidth;
      var tempHeight = origHeight;
      
      for (var j = (current - 1); j > (lower) - 1; j--, i++) {
				var li = $(lis[j]);
				var img = li.children('a').children('img');
				tempWidth = tempWidth * config.reductionMultiplier;
				tempHeight = tempHeight * config.reductionMultiplier;
				li.animate({
				  width: tempWidth,
				  height: tempHeight,
          opacity: 1
				});
				img.animate({
				  width: tempWidth,
				  height: tempHeight,
          opacity: 1
				});
				li.attr('class', 'bg' + i.toString());
      }
      
      i = 1;
      tempWidth = origWidth;
      tempHeight = origHeight;
      
      for (var j = (current + 1); j < (upper) + 1; j++, i++) {
        var li = $(lis[j]);
				var img = li.children('a').children('img');
				tempWidth = tempWidth * config.reductionMultiplier;
				tempHeight = tempHeight * config.reductionMultiplier;
				li.animate({
				  width: tempWidth,
				  height: tempHeight,
          opacity: 1
				});
				img.animate({
				  width: tempWidth,
				  height: tempHeight,
          opacity: 1
				});
				li.attr('class', 'bg' + i.toString());
      }
    }
    
    this.each(function(i, val) {
      that = $(val);
			initialize();
			if (config.autoRotate) {
				refreshTimeout();
			}
		});
		
		function refreshTimeout() {
			timeoutVar = setTimeout(function() {
				runNext();
			}, config.timeoutInterval);
		}
		
		function runNext() {
			nextButtonClicked(true);
		}
		return this;
  }
})(jQuery);