/****************
 *
 * Animates a color overlay in tiles.
 *
 * Usage: $.tiledOverlayReveal({
 *		'tileColor': '#FFFFFF',
 *		'tileWidth': 80,
 *		'tileHeight': 70,
 *		'tileZIndex': 10000,
 *		'lastTileDelay': 300, // each tile is increasingly delayed this being the longest delay
 *		'tileFadeDuration': 300, // each tile fades in or out in this time
 *		'callback': function() {} // the function to call after finished
 * });
 *
 * Usage: $('a.out').tiledOverlayCover(options);
 * Usage: $.tiledOverlayGet().animate(options, revealElseCover, optionalTargetURL); 
 *
 * @author teemu@debyte.fi
 *
 ****************/

// Wrapper to ensure $ is jQuery.
(function($) {

	/**
	 * Reveals page under tiled overlay.
	 * @param options the options for the overlay animation
	 */
	$.tiledOverlayReveal = function(options)
	{
		$.tiledOverlayGet().animate(options, true);
	}

	/**
	 * Covers the page under tiled overlay when any matched elements are clicked.
	 * @param options the options for the overlay animation
	 */
	$.fn.tiledOverlayCover = function(options)
	{
		return this.click(function(event)
		{
			event.preventDefault();
			$.tiledOverlayGet().animate(options, false, $(this).attr('href'));
		});
	}

	/**
	 * Constructs or gets the tiled overlay plugin.
	 */
	$.tiledOverlayGet = function()
	{
		$body = $('body');
		
		// Construct new plugin or use existing.
		var plugin = $body.data('TiledOverlayPlugin');
		if (plugin == undefined)
		{
			plugin = new $.TiledOverlayPlugin($body);
			$body.data('TiledOverlayPlugin', plugin);
		}
		return plugin;
	}

	/**
	 * Plugin constructor.
	 * @param element the element to place animation in
	 */
	$.TiledOverlayPlugin = function(element)
	{
		var plugin = this;
		var $element = $(element);

		var defaults = {
			'tileColor': '#FFFFFF',
			'tileWidth': 80,
			'tileHeight': 70,
			'tileZIndex': 10000,
			'lastTileDelay': 300,
			'tileFadeDuration':300,
			'callback': null,
		};

		/**
		 * Starts tile animation.
		 * @param options the options for the animation
		 */
		plugin.animate = function(options, revealElseCover, optionalTargetURL)
		{
			// Clean any existing overlays before starting.
			plugin.cleanup();
	
			// Handle parameters.
			var config = $.extend({}, defaults, options);
			plugin.callback = config.callback;
			plugin.directionReveal = revealElseCover;
			plugin.optionalTargetURL = optionalTargetURL;

			// Create a tile element for cloning.
			var $tile = $('<div class="tiled-overlay" />').css({
				'position': 'absolute',
				'z-index': config.tileZIndex,
				'width': config.tileWidth + 'px',
				'height': config.tileHeight + 'px',
				'background-color': config.tileColor,
				'opacity': 1
			});
			var targetOpacity = 0;
			if (!plugin.directionReveal)
			{
				$tile.css('opacity', 0);
				targetOpacity = 1;
			}

			// Loop through each tile.
			var cols = Math.ceil($(window).width() / config.tileWidth);
			var rows = Math.ceil($(window).height() / config.tileHeight);
			var max = cols + rows - 2;
			for (var y = 0; y < rows; y++)
			{
				for (var x = 0; x < cols; x++)
				{
					var d = (x + y) / max - 1;
					if (d == 0)
					{
						$element.append($tile.clone()
							.css({ 'top': (y * config.tileHeight) + 'px', 'left': (x * config.tileWidth) + 'px' })
							.delay(config.lastTileDelay)
							.animate({ 'opacity': targetOpacity }, config.tileFadeDuration, 'swing', plugin.finish)
						);
					}
					else
					{
						$element.append($tile.clone()
							.css({ 'top': (y * config.tileHeight) + 'px', 'left': (x * config.tileWidth) + 'px' })
							.delay(config.lastTileDelay * (d * d * d + 1))
							.animate({ 'opacity': targetOpacity }, config.tileFadeDuration)
						);
					}
				}
			}
		}

		/**
		 * Callback when tile animations are finished.
		 */
		plugin.finish = function()
		{
			if (plugin.directionReveal)
			{
				plugin.cleanup();
			}
			if (plugin.callback)
			{
				plugin.callback();
			}
			if (plugin.optionalTargetURL)
			{
				window.location.href = plugin.optionalTargetURL;
			}
		}

		/**
		 * Cleans the page overlay out.
		 */
		plugin.cleanup = function()
		{
			$('div.tiled-overlay').remove();
		}

		// Clean the overlay on window unload. Safari might recycle the page back to use.
		$(window).unload(plugin.cleanup);
	}

})(jQuery);

