/*
 * 
 * jQuery Cycle v1.0
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2009 Travis Beckham (squidfingers.com)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer. Redistributions in binary
 * form must reproduce the above copyright notice, this list of conditions and
 * the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to
 * endorse or promote products derived from this software without specific
 * prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
*/

(function($){
	
	$.fn.cycle = function(settings){
		
		settings = $.extend({}, $.fn.cycle.defaults, settings);
		
		var self = this;
		var imageIndex = 0;
		var imageCount = settings.images.length;
		var timer = null;
		var imageReady = false;
		var transitionReady = false;
		
		if (imageCount) {
			// add classname to cycle div
			$(self).addClass('cycle');
			// remove any contents in the cycle div
			$(self).empty();
			// insert the first image
			$(self).append(getHTML('imageA', 0));
			// wait until the image has loaded
			$(self).find('div.imageA img').load(function(){
				onFirstImageReady();
			});
		}
		
		function onFirstImageReady(){
			// reveal the cycle div
			$(self).css({visibility:'visible'});
			// set the cycle div's width and height to match the first image
			var img = $(self).find('div.imageA img');
			var w = img.width();
			var h = img.height();
			if (w > 0 && h > 0) {
				$(self).css({width:w,height:h});
			}
			// if there is more than one image...
			if (imageCount > 1) {
				// insert the second image
				$(self).append(getHTML('imageB', 1));
				// attach event to determine when the second image is loaded
				imageReady = false;
				$(self).find('div.imageB img').load(function(){
					onNextImageReady();
				});
				// start cycle
				timer = setTimeout(onTimerComplete, settings.interval);
			}
		}
		function onTimerComplete(){
			imageIndex = getNextIndex();
			transition();
		}
		function onNextImageReady(){
			imageReady = true;
			if (transitionReady) {
				transition();
			}
		}
		function getNextIndex(){
			return (imageIndex == imageCount - 1) ? 0 : imageIndex + 1;
		}
		function getHTML (name, index) {
			var img = '<img src="'+settings.images[index]+'" alt="" />';
			if (settings.link) img = '<a href="'+settings.link+'">'+img+'</a>';
			return '<div class="'+name+'">'+img+'</div>';
		}
		function transition(){
			// make sure the next image is loaded before running the transition
			if ( ! imageReady) {
				transitionReady = true;
				return;
			}
			// determine the width and height of both images
			var imgA = $(self).find('div.imageA img');
			var imgB = $(self).find('div.imageB img');
			var wA = imgA.width();
			var wB = imgB.width();
			var hA = imgA.height();
			var hB = imgB.height();
			// determine which image is smaller
			var w = Math.min(wA, wB);
			var h = Math.min(hA, hB);
			// determine if the cycle div needs to be resized
			if ( (wA != wB || hA != hB) && (w > 0) && (h > 0) ) {
				// animate the cycle div's width and height
				$(self).animate({width:w,height:h}, 500, 'swing', function(){
					if ( (wB == w) && (hB == h) ) {
						transitionPart2();
					} else {
						transitionPart2(wB, hB);
					}
				});
			} else {
				transitionPart2();
			}
		}
		function transitionPart2 (w, h) {
			// real the next image
			$(self).find('div.imageB').css({visibility:'visible'});
			// fade out the current image
			$(self).find('div.imageA').animate({opacity:0}, 1000, 'linear', function(){
				// remove the current image
				$(self).find('div.imageA').remove();
				// swap the class name of the next image making it the current image
				$(self).find('div.imageB').removeClass('imageB').addClass('imageA');
				// insert the next image
				$(self).append(getHTML('imageB', getNextIndex()));
				// attach event to determine when the next image is loaded
				imageReady = false;
				$(self).find('div.imageB img').load(function(){
					onNextImageReady();
				});
				// determine if the cycle div needs to be resized
				if (w && h) {
					// animate the cycle div's width and height to the size of the current image
					$(self).animate({width:w, height:h}, 500, 'swing', function(){
						transitionPart3();
					});
				} else {
					transitionPart3();
				}
			});
		}
		function transitionPart3(){
			// transition complete
			transitionReady = false;
			timer = setTimeout(onTimerComplete, settings.interval);
		}
		
		return self;
	};
	
	$.fn.cycle.defaults = {
		images: new Array(),
		link: null,
		interval: 5000
	};
	
})(jQuery);

