/**
*	@name DarkBox
*	@version 1.0.0
*	@description A jQuery Lightbox Plugin
*	@author Trey Shugart
*	@date 2008-02-26
*	@copyright Copyright 2008 Trey Shugart
*	@license GNU LGPL (http://www.gnu.org/licenses/lgpl.html)
*	
*	Requires the plugins getOffsets and realOffsets.
*
*	You may pass your own html as a string or use the predefined html. If you do this, your markup
*	must conform to certain standards of course. Mainly, these standards conclude that you must
*	contain your layout in a container with a default id of 'darkbox-container'. This can be changed, but
*	you must pass the custom id to the script so that DarkBox knows which element is the container.
*	This also goes for the other main elements inside of the container. Certain elements required a
*	specific id so they can be manipulated by darkbox. Fortunately, these can be changed by passing
*	them to the script if need be. The other standard you must take into account that the only element
*	being resized is the container (#darkbox-container). This means that the rest is up to you. You can
*	place elements anywhere inside of the container, outside of the container (if you do not wish for them
*	to move with the container), eliminate them altogether (but why would you do that?). You can also
*	add elements that aren't normally in lightbox. Depending on your html and css, there are many
*	possibilities.
*
*	Oh, almost forgot, if you want a backdrop such as a black div, or something else, you must also include
*	a block level element that is not contained in the container (#darkbox-container) and give it an id. The
*	default id is 'darkbox-backdrop'.
*	
*	List of default id's, what they correstpond to and their option name are below:
*		Format: [option name] : [default id] : [required] : [explanation]
*		- backdrop : darkbox-backdrop : no : The backdrop such as a black background behind the darkbox window
*		- container : darkbox-container : yes : The containing element of the darkbox window. This is the meat and potatoes.
*		- image : darkbox-image : no : The container for the image. The image gets appended to this.
*		- nav : darkbox-nav : no : The container for the next and previous buttons
*		- info : darkbox-info : no : The container for the title, image [num] of [num] and close button
*		- title : darkbox-title : no : Contains the title of the image
*		- number : darkbox-number : no : Contains the text 'Image [num] of [num]'
*		- btnPrev : darkbox-btn-prev : yes : Goes to the previous image
*		- btnNext : darkbox-btn-next : yes : Goes to the next image
*		- btnClose : darkbox-btn-close : yes : Closes the window
*		- loader : darkbox-loader : no : Displays a loading image
*/
(function($) {
	$.fn.darkbox = function(p) {
		var $$ = $(this);
		
		if ($$.length === 0) {
			return false;
		}
		
		var darkbox, styles, container, image, nav, info, title, number, btnNext, btnPrev, btnClose, loader, currentImageIndex;
		var params = $.extend({
			html: '',
			css: '',
			backdrop: 'darkbox-backdrop', // backdrop id
			container: 'darkbox-container', // container id
			image: 'darkbox-image', // image container id
			nav: 'darkbox-nav', // navigation container id
			info: 'darkbox-info', // information container id
			title: 'darkbox-title', // image title id
			number: 'darkbox-number', // image [num] of [num] container id
			btnNext: 'darkbox-btn-next', // next button id
			btnPrev: 'darkbox-btn-prev', // previous button id
			btnClose: 'darkbox-btn-close', // close button id
			loader: 'darkbox-loader', // loading image id
			
			start: 0, // zero indexed
			end: 0, // zero indexed, will limit to the image at this index if set to greater than zero
			
			stylesLoaded: false // set to true if you manually set your styles
		}, p);
		
		if (!$.isFunction($.fn.realOffset) || !$.isFunction($.fn.getOffsets) || !$.isFunction($.pageSize)) {
			return false;
		}
		
		// default the html if there wans't custom html passed
		if (params.html === '') {
			params.html = "<div id=\""+params.backdrop+"\"></div><div id=\""+params.container+"\">\n\t<div id=\""+params.loader+"\">loading...</div>\n\t<div id=\""+params.image+"\"></div>\n\t<div id=\""+params.nav+"\">\n\t\t<a id=\""+params.btnPrev+"\" href=\"javascript:;\">&laquo; prev</a>\n\t\t<a id=\""+params.btnNext+"\" href=\"javascript:;\">next &raquo;</a>\n\t</div>\n\t<div id=\""+params.info+"\">\n\t\t<div id=\""+params.title+"\"></div>\n\t\t<div id=\""+params.number+"\"></div>\n\t\t<a id=\""+params.btnClose+"\" href=\"javascript:;\">close</a>\n\t</div>\n</div>";
		}
		
		// load the CSS
		if (params.css !== '') {
			// if the css is a file name, load the css
			if (params.css.match(/(.*)+\.[a-zA-Z0-9]+/)) {
				params.css = '<link id="darkbox-style" rel="stylesheet" type="text/css" href="'+params.css+'" />';
			// otherwise assume that params.css is valid css code
			} else {
				params.css = '<style id="darkbox-style" type="text/css">'+params.css+'</style>';
			}
		// default styles
		} else if (params.css === '') {
			params.css = '<style id="darkbox-style" type="text/css">';
			params.css += '#'+params.backdrop+' {background-color: #000; z-index: 1000;}';
			params.css += '#'+params.container+' {background-color: #fff; padding: 34px 10px 50px 10px; width: 300px; height: 300px; z-index: 1001;}';
			params.css += '#'+params.container+' a {color: #666; padding: 1px; text-decoration: none; }';
			params.css += '#'+params.container+' a:hover {background-color: #ddd;}';
			params.css += '#'+params.loader+' {position: absolute; top: 0; left: 0; font-weight: bold; font-size: 1.2em;}';
			params.css += '#'+params.nav+' {position: absolute; top: 0; left: 0; padding: 10px;}';
			params.css += '#'+params.btnPrev+' {float: left;}';
			params.css += '#'+params.btnNext+' {float: right;}';
			params.css += '#'+params.btnClose+' {position: absolute; right: 10px; bottom: 10px; font-size: 1.2em; font-weight: bold;}';
			params.css += '#'+params.info+' {margin-top: 10px; text-align: left;}';
			params.css += '#'+params.title+' {font-weight: bold;}';
			params.css += '</style>';
		}
		
		init();
		
		function init() {
			if (params.html == '') {
				return false;
			}
			
			// assign variables because we will remove them later
			styles = $(params.css).appendTo('head'); // create the css code
			darkbox = $(params.html).appendTo('body'); // create the main container
			
			// makes code easier and things easier
			backdrop = $('#'+params.backdrop);
			container = $('#'+params.container);
			image = $('#'+params.image);
			nav = $('#'+params.nav);
			info = $('#'+params.info);
			title = $('#'+params.title);
			number = $('#'+params.number);
			btnPrev = $('#'+params.btnPrev);
			btnNext = $('#'+params.btnNext);
			btnClose = $('#'+params.btnClose);
			loader = $('#'+params.loader);
			
			// appropriately hide elements
			backdrop.hide();
			container.hide();
			loader.hide();
			image.hide();
			info.hide();
			btnPrev.hide();
			btnNext.hide();
			
			// btn visibility
			if (params.start !== 0) {
				btnPrev.show();
			}
			if ((params.start + 1) < $$.length) {
				btnNext.show();
			}
			
			// apply mandatory css and overwrite custom if necessary
			backdrop.css({
				'position': 'absolute',
				'width': $.pageSize(0),
				'height': $.pageSize(1),
				'left': 0,
				'top': 0,
				'opacity': 0
			});
			
			// actions
			backdrop.click(close);
			btnPrev.click(prevImage);
			btnNext.click(nextImage);
			btnClose.click(close);
			
			open();
		};
		
		function open() {
			backdrop.fadeTo('fast', .65, function() {
				// in some cases, I had trouble with the styles not being loaded yet, so this is done here
				// to give the stylesheet the maximum amount of time to load
				container.css({
					'position': 'absolute',
					'top': $.pageScroll('y') + 5,
					'left': ($.pageSize(2) / 2) - (container.width() / 2) + $.pageScroll('x')
				});
				// this relies on the container's width and height so this must be done after the above css declarations on the container
				loader.css({
					'top': (container.height() / 2) - (loader.height() / 2),
					'left': (container.width() / 2) - (loader.width() / 2)
				});
				container.fadeIn('fast', function() {
					loadImage(params.start);
				});
			});
		};
		
		function close() {
			container.fadeOut('fast', function() {
				backdrop.fadeOut('fast', function() {
					destroy();
				});
			});
		};
		
		function destroy() {
			darkbox.remove();
			styles.remove();
		};
		
		function loadImage(index) {
			if (typeof(currentImageIndex) !== 'undefined') {
				image.fadeOut('fast', function() {
					image.children('img:first').remove();
				});
				info.fadeOut('fast');
			}
			
			var a = $$.eq(index);
			var img = $('<img alt="'+a.attr('title')+'" />').appendTo(image);
			var imgPreloader = new Image();
			var showLoader = setTimeout(function() {
				loader.fadeIn('fast');
			}, 500);
			
			// set the current images index
			currentImageIndex = index;
			
			// set the navigation elements
			setNav();
			imgPreloader.onload = function() {
				clearTimeout(showLoader);
				loader.filter(':visible').fadeOut('fast');
				container.animate({
					top: $.pageScroll('y') + 5,
					left: ($.pageSize(2) / 2) - (imgPreloader.width / 2) + $.pageScroll('x'),
					width: imgPreloader.width,
					height: imgPreloader.height
				}, 500, 'swing', function() {
					img.attr('src', a.attr('href'));
					title.html(a.attr('title'));
					number.html('Image '+(currentImageIndex + 1)+' of '+$$.length);
					image.fadeIn('fast');
					info.fadeIn('fast');
					image.width(imgPreloader.width).height(imgPreloader.height);
				});
			}
			
			imgPreloader.src = a.attr('href');
			loader.css({
				top: (container.height() / 2) - (loader.height() / 2),
				left: (container.width() / 2) - (loader.width() / 2)
			});
		};
		
		function prevImage() {
			if (currentImageIndex > 0) {
				loadImage(currentImageIndex - 1);
			}
		};
		
		function nextImage() {
			if (currentImageIndex < ($$.length - 1)) {
				loadImage(currentImageIndex + 1);
			}
		};
		
		function setNav() {
			if (currentImageIndex === 0) {
				btnPrev.filter(':visible').fadeOut('fast');
			} else {
				btnPrev.filter(':hidden').fadeIn('fast');
			}
			if (currentImageIndex === ($$.length - 1)) {
				btnNext.filter(':visible').fadeOut('fast');
			} else {
				btnNext.filter(':hidden').fadeIn('fast');
			}
		};
	};
})(jQuery);