/**
 * Lightcrate jQuery plug-in
 * 
 * Flexible "fancy" message pop-up add-on. 
 * 
 * Inspired by Lightbox from Lokesh Dhakar. http://www.lokeshdhakar.com/projects/lightbox2/
 * 
 **/
 

(function($) {
$.fn.lightcrate = function( options ) {

	/**
	 * 	Define default options/settings.
	 */
	options = $.extend({
		event		: 'click',		// Event to attach to start animation.
		
		bgClass		: 'cratebg',	// Class for background overlay.
		bgColor		: '#000',		// Color for background overlay.
		bgInSpeed	: 0,			// Background animation speed in.
		bgOutSpeed	: 0,			// Background animation speed out.
		bgOpacity	: 0.85,			// Background opacity level.
		boxClass	: 'crate',		// Class for box.
		boxInSpeed	: 'normal',		// Box animation speed in.
		boxOutSpeed	: 'normal',		// Box animation speed out.
		boxOpacity	: 1.0,			// Box opacity.
		boxHeight	: 0,			// Box height. If 0, resizes to size of content.
		boxWidth	: 0,			// Box width. If 0, resizes to size of content.
		closeClass	: 'closer',		// Class for close button.
		content		: 'imgsrc',		// Which content you want to use. imgsrc, function, html, id or class, attribute
		easing		: 'swing',		// Animation easing.
		hideSource	: false,		// Hide source element of animation.
		loadimg		: '/images/loader.gif',		// Source of loading image.
		nextnav		: 'Next',		// Text for "next" navigation button.
		preloadimg	: false,		// Whether images should pre-load before event attachment.
		prevnav		: 'Previous',	// Text for "previous" navigation button.
		sequence	: false,		// Whether element series should be shown in a sequence.
		startPos	: {x:0, y:0}	// Starting position of box animation. Coordinates, center, or element.
	}, options);


	/**
	 * Define elements.
	 */
	var elems = this, size = elems.length, total = (elems.length - 1), contents = new Array(), loader = new Image();
	var bg = $('<div></div>'), crate = $('<div></div>'), content_wrap, closer;
	var next, prev;
	var contentX, contentY, contentW, contentH;
	loader.src = options.loadimg;

	
	/**
	 * Start lightcrate.
	 */
	return this.each( function() {
		
		var elem = this;
		var content, index;

		//	Dimensions.
		var bodyW = $('body').width(), bodyH = $(window).height(), scrollX = $(window).scrollLeft(), scrollY = $(window).scrollTop();
		var centerX = (bodyW / 2) + scrollX, centerY = (bodyH / 2) + scrollY, elX, elY;

		if ( jQuery.isFunction( options.content ) ) {
			content = options.content( elem );
			$(elem).bind( options.event, _start );
		} else if ( options.content == 'html' ) {
			content = $(elem).html();
			$(elem).bind( options.event, _start );
		} else if ( options.content == 'imgsrc' ) {
			if( options.preloadimg === false )
			{
				$(elem).bind( options.event, _start );
			} else {
				content = $('<img>').attr('src', $(elem).attr('href') );
				$(content).bind('load', function(){
					$(elem).bind( options.event, _start );
				})
			}
		} else if ( /\.\#/.test(options.content) ) {
			content = $(options.content);
			$(content).bind( 'load', function(){
				$(elem).bind( options.event, _start );
			});
		} else {
			content = $(elem).attr(options.content);
			$(elem).bind( options.event, _start );
		}
		if( options.event == 'load' && $(elems).index(this) == 0 )
			_start();
		
		
		/**
		 * _start()
		 * 
		 * Start the lightcrate process.
		 */
		function _start()
		{
			index = $(elems).index(elem);

			if( options.hideSource == true )
				$(elem).hide();

			_show_loading();
			_show_bg();
			if( options.content == 'imgsrc' )
			{
				content = $('<img>').attr('src', $(elem).attr('href') );
				$('body').append(content);

				$(content).bind( 'load', function(){
					_get_content();
					_show_crate();
				})
			} else {
				_get_content();
				_show_crate();
			}

			return false;
		}
		
		
		/**
		 * _create_bg()
		 * 
		 * Crate background div.
		 */
		function _create_bg()
		{
			$(bg).css({
				'background': options.bgColor,
				'display'	: 'none',
				'height'	: $(document).height() ,
				'left'		: scrollX,
				'opacity'	: options.bgOpacity,
				'position'	: 'absolute',
				'top'		: 0,
				'width'		: '100%',
				'z-index'	: 1000
			})
			.addClass(options.bgClass);
			$('body').append(bg);
		}
		
		
		/**
		 * _create_crate()
		 * 
		 * Create crate div.
		 */
		function _create_crate()
		{
			$(crate).css({
				'background': '#fff',
				'opacity'	: 0.00,
				'overflow'	: 'visible',
				'padding'	: '1em',
				'position'	: 'absolute',
				'z-index'	: 1010
			})
			.addClass(options.boxClass);
			
			content_wrap = $('<div></div>').css({
				'clear'		: 'both',
				'display'	: 'block'
			});
		}
		
		
		/**
		 * _create_closer()
		 * 
		 * Crate close button
		 */
		function _create_closer()
		{
			closer = $('<a></a>').attr('href','#')
			.html('Close')
			.attr('title','Click to close OR press ESC')
			.addClass( options.closeClass )
			.css({
				'background'	: '#fff',
//				'border'		: '2px solid #333',
				'bottom'		: 5,
				'clear'			: 'both',
				'color'			: '#555',
				'font'			: 'bold 16px arial, verdana, helvetica',
				'padding'		: '0.1em 0.3em',
				'position'		: 'absolute',
//				'left'			: -12,
				'text-decoration'	: 'none',
//				'top'			: -12,
				'z-index'		: 1020,
				'-moz-border-radius'	: 3
			})
			.bind( 'click', _hide_all );			
		}
		
		
		/**
		 * _create_nav()
		 * 
		 * Create navigation buttons.
		 */
		function _create_nav()
		{
			next = $('<a></a>').attr('href','#')
			.html( options.nextnav )
			.addClass('nextnav')
			.css({
				'background'	: '#fff',
				'color'			: '#555',
				'display'		: 'none',
				'padding'		: '0.5em',
				'position'		: 'absolute',
				'right'			: 0,
				'top'			: '15%',
				'z-index'		: 1050
			})
			.bind( 'click', _move_next );

			prev = $('<a></a>').attr('href','#')
			.html( options.prevnav )
			.addClass('prevnav')
			.css({
				'background'	: '#fff',
				'color'			: '#555',
				'display'		: 'none',
				'padding'		: '0.5em',
				'position'		: 'absolute',
				'left'			: 0,
				'top'			: '15%',
				'z-index'		: 1050
			})
			.bind( 'click', _move_prev );
		}
		
		
		/**
		 * _get_content()
		 * 
		 * Get content information and push into array.
		 */
		function _get_content()
		{
			if( size > 1 ) {
				var c;
				$(elems).each( function(){
					if ( jQuery.isFunction( options.content ) ) {
						c = options.content( this );
					} else if ( options.content == 'html' ) {
						c = $(this).html();
					} else if ( options.content == 'imgsrc' ) {
						c = new Image();
						c.src = $(this).attr('href');
					} else if ( /\.\#/.test(options.content) ) {
						c = $(options.content);
					} else {
						c = $(this).attr(options.content);
					}
					contents.push(c);
				});
			}

			contentW = content.width > 0 ? content.width : $(content).width();
			contentH = content.height > 0  ? content.height : $(content).height
			
			//	Unbind element event.
			$(elem).unbind(options.event);
		}
		
		
		/**
		 * _show_bg()
		 * 
		 * Show background layer.
		 */
		function _show_bg()
		{
			_create_bg();	//	Create background.
			
			//	Display background.
			if( options.bgInSpeed == 0)
				options.bgInSpeed = 1;
			$(bg).fadeIn( options.bgInSpeed );
		}
		
		
		/**
		 * _show_crate()
		 * 
		 * Show crate layer.
		 */
		function _show_crate()
		{
			_create_crate();	//	Create crate.
			
			//	Prepare crate.
			$(crate).append(content)
			.css({
				'display'	: 'none'
			});
			$('body').append(crate);
			
			_create_closer();	//	Create close button.

			_crate_move();	// Animate box.
		}
		
		
		/**
		 * _show_loading()
		 * 
		 * Display loading image.
		 */
		function _show_loading()
		{
			scrollX = $(window).scrollLeft(), scrollY = $(window).scrollTop(), centerX = (bodyW / 2) + scrollX, centerY = (bodyH / 2) + scrollY;
			var loadH = loader.height, loadW = loader.width;
			var loadY = centerY - (loadH / 2), loadX = centerX - (loadW / 2);
			
			$(loader).css({
				'position'		: 'absolute',
				'left'			: loadX,
				'top'			: loadY,
				'z-index'		: 1001
			});
			$('body').append(loader);
		}
		
		
		/**
		 * _crate_move()
		 * 
		 * Animate crate move position.
		 */
		function _crate_move()
		{
			scrollX = $(window).scrollLeft(), scrollY = $(window).scrollTop(), centerX = (bodyW / 2) + scrollX, centerY = (bodyH / 2) + scrollY;
			var offset = $(elem).offset();
			if( options.startPos == 'element' )
				elX = offset.left, elY = offset.top;
			else if( options.startPos == 'center' )
				elX = centerX, elY = centerY;
			else
				elX = options.startPos.x, elY = options.startPos.y;
			
			var targetW = contentW > 0 ? contentW : $(crate).width();
			var targetH = contentH > 0 ? contentH : $(crate).height();
			var boxX = centerX - (targetW / 2), boxY = centerY - (targetH / 2);
			targetH = targetH + $(closer).height() + 20;
			
			_hide_loading();	//	Hide loading image.
		
			_create_nav();	//	Create navigation.
									
			$(crate).css({
				'height'	: 0,
				'left'		: elX,
				'top'		: elY,
				'width'		: 0
			})
			.html('');
			
			$(content_wrap).html('');
			
			$(crate).animate(
				{ width:targetW, height:targetH, top:boxY, left:boxX, opacity:1.0 },
				{ 'duration':options.boxInSpeed, 'easing':options.easing, complete:function(){
//					$(this).append(closer).append(content);
					$(content_wrap).append(content);
					$(this).append(content_wrap).append(closer);
					$(document).bind( 'keypress', _navigation );
					
					//	Determine if navigation should be shown.
					if( size > 1 && options.sequence === true ) {
						$(crate).append(prev).append(next);
						if( index > 0 )
							$(crate).append(prev);
						else
							$(prev).remove();

						if( index < total )
							$(crate).append(next);
						else
							$(next).remove();
					}

				}}
			).hover( 
				function(){ _nav_toggle( boxX ); },
				function(){ $(next).hide(); $(prev).hide(); }
			);
			
		}
		
		
		/**
		 * _nav_toggle()
		 * 
		 * Toggle navigation items.
		 */
		function _nav_toggle( left )
		{
			var left = left, right = (left + $(crate).width());
			var split = ((left + right) / 2);
			
			$(crate).mousemove(
				function(e){
					( e.pageX > left && e.pageX < split ) ? $(prev).show() : $(prev).hide();
					( e.pageX > split ) ? $(next).show() : $(next).hide();
				}
			)
		}
		
		
		/**
		 * _crate_size()
		 * 
		 * Animate crate size.
		 */
		function _crate_size()
		{
			
			var targetW = contentW > 0 ? contentW : $(crate).width();
			var targetH = contentH > 0 ? contentH : $(crate).height();
			var boxX = centerX - (targetW / 2), boxY = centerY - (targetH / 2);
			targetH = targetH + $(closer).height();
			
			//	Reset events.
			$(next).unbind('click')
			.bind( 'click', _move_next );
			$(prev).unbind('click')
			.bind( 'click', _move_prev );
			
			_create_closer();	//	Create close button.
		
			_create_nav();	//	Create navigation.
			
			$(content_wrap).html('');

			$(crate).html('')
			.animate(
				{ width:targetW, height:targetH, top:boxY, left:boxX },
				{ 'duration':options.boxInSpeed, 'easing':options.easing, complete:function(){
//					$(this).append(closer).append(content);
					$(content_wrap).append(content);
					$(this).append(content_wrap).append(closer);

					//	Determine if navigation should be shown.
					if( size > 1 && options.sequence === true ) {
						if( index > 0 )
							$(crate).append(closer).append(prev);
						else
							$(prev).remove();

						if( index < total )
							$(crate).append(next);
						else
							$(next).remove();
					}
				}}
			).hover( 
				function(){ _nav_toggle( boxX ); },
				function(){ _nav_toggle( boxX ); }
			);
		}
		
		
		/**
		 * _move_next()
		 * 
		 * Move to next content item in sequence.
		 */
		function _move_next()
		{
			if( index++ >= total ) {
				index--;
				return false;
			}
			
			content = contents[index];
			
			contentW = content.width;
			contentH = content.height;
			
			_crate_size();
			return false;
		}
		
		
		/**
		 * _move_prev()
		 * 
		 * Move to previous content item in sequence.
		 */
		function _move_prev()
		{
			if( index-- <= 0 ) {
				index++;
				return false;
			}
			
			content = contents[index];
			
			contentW = content.width;
			contentH = content.height;
			
			_crate_size();
			return false;
		}
		
		
		/**
		 * _hide_all()
		 * 
		 * Hide all elements.
		 */
		function _hide_all()
		{
			//	Hide background element.
			if( options.bgOutSpeed == 0 )
				options.bgOutSpeed = 1;
			$(bg).fadeOut( options.bgOutSpeed, function(){ $(this).remove() } );
			
			_hide_loading(); //	Hide loading image.
			
			//	Return crate animation.
			$(next).remove();
			$(prev).remove();
			$(crate).html('')
			.animate(
				{ width:0, height:0, top:elY, left:elX, opacity: 0.0 },
				{ 'duration':options.boxOutSpeed, 'easing':options.easing, complete:function(){
					$(this).remove();
					$(this).css({width:null,height:null});
					$(document).unbind('keypress');
					//	Rebind event.
					$(elem).bind( options.event, _start );
				}}
			);
			return false;
		}
		
		
		/**
		 * _hide_loading()
		 * 
		 * Hide loading image.
		 */
		function _hide_loading()
		{
			$(loader).remove();
		}
		
		
		/**
		 * _navigation()
		 * 
		 * Handle keyboard navigation.
		 */
		function _navigation(event)
		{
			var c = String.fromCharCode(event.which), code = event.keyCode;
			var escapeKey = event.DOM_VK_ESCAPE ? event.DOM_VK_ESCAPE : escapeKey = 27;

			if( code == escapeKey )
				_hide_all();
				
			switch( c ) {
				case 'x' : case 'c' :
					_hide_all(); break;
				case '.' :
					if( options.sequence === true )
						_move_next(); 
						break;
				case ',' :
					if( options.sequence === true )
						_move_prev(); 
						break;
			}
			
			switch( code ) {
				case 37 :
					if( options.sequence === true )
						_move_prev(); 
						break;
				case 39 :
					if( options.sequence === true )
						_move_next(); 
						break;
			}
		}
	});
	
}
})(jQuery);