jQuery.fn.gallerize = function (settings) {
	//Initialize settings
	settings = jQuery.extend({
		borderSize: 22,
		opacity: .5,
		speed: 200
	}, settings);
	
	//Initialize variables
	var virgin    = true;  //The gallery is a virgin whenever it is opened
	var current   = 0;     //The current index of the image
	var imgURLs   = [];    //Array retains the <a>'s that hold the image url's
	var hovering  = false; //True when the mouse is over the image box
	var animating = true;  //True when animating
	
	//Retain image URLs and add click() events
	$(this).find("a").each(function() {
		//Store index for later
		$(this).data('index', imgURLs.length);
		
		//Retain
		imgURLs[imgURLs.length] = this;
		
		//Open on click
		$(this).click(function(e) {
			e.preventDefault();
			this.blur();
			open(this);
		});
	});
	
	//Opens the gallery to the specified image
	function open (url) {
		//Append HTML source
		$("body").append(__gallerizeHTMLSource__);

		//The Gallery is a virgin
		virgin = true;
		
		//Set events for navigation arrows if more than one image
		if (imgURLs.length > 1) {
			//Previous arrow
			$("#g-prev").click(function (e) {
				e.preventDefault();
				this.blur();
				loadImage(imgURLs[current - 1]);
			});
			
			//Next arrow
			$("#g-next").click(function (e) {
				e.preventDefault();
				this.blur();
				//parseInt for some bizarre quirk that makes it a string
				loadImage(imgURLs[parseInt(current) + 1]); 
			});
		}
		
		//Set Keyboard events
		$(document).bind('keyup', handleKeyboard);
		
		//Set hover event on the image box for fading the title
		$("#g-wrapper").hover(
			function () {
				hovering = true;
				if (!animating) {
					$("#g-title-wrapper")
						.css({ opacity: 0, display: 'block' })
						.fadeTo(settings.speed, 1, function(){ fixIEFilters(this); });
				}
			},
			function () {
				hovering = false;
				$("#g-title-wrapper").fadeTo(settings.speed, 0);
			}
		);
		
		//Components are set to display: none by default
		$("#gallerize-components").css('display', 'block');
		
		//Begin the process of animating everything in
		$("#g-overlay")
			//Quit when overlay is clicked
			.click(function() { close(); })
			
			//Prep for fading in
			.css({ opacity: 0, display: 'block' })
			
			//Fade in the overlay
			.fadeTo(settings.speed, settings.opacity, function() {
				//Set default size and position of the box, 100x100
				$("#g-wrapper")
					.css({
						width:   100 +'px',
						height:  100 +'px',
						top:     $(window).height() / 2 - 50 - settings.borderSize +'px',
						left:    $(window).width()  / 2 - 50 - settings.borderSize +'px',
						display: 'block',
						opacity:  0
					})
					
					//Fade in the box
					.fadeTo(settings.speed, 1, function () {
						//restore PNG transparency in IE
						fixIEFilters(this);
						//Reload the image and display
						loadImage(url);
					});
			});
	};
	
	function loadImage (url) {
		//Initialize preloader
		var preload = new Image();
		
		//We're still animating
		animating = true;
		
		//current is used when navigating between images
		current = $(url).data('index');
		
		//Display relevant navigation arrows
		$("#g-prev").css('display', (current > 0) ? 'block' : 'none');
		$("#g-next").css('display', (current != imgURLs.length - 1) ? 'block' : 'none');
		
		//Begin animating images
		$("#g-image")
			//Fade out the current image, if any
			.fadeTo(virgin ? 0 : settings.speed, 0, function () { 
				//Eet 'as been deefiled
				virgin = false;
				
				//Fade out the image title
				$("#g-title-wrapper").fadeTo(settings.speed, 0);
				
				//Preload the image
				$(preload)
					.load(function() {
						//Resize the image if it's bigger than the viewport
						preload = setMaxDimensions(preload);
						
						//Begin box resizing animation
						$("#g-wrapper")
							.animate({
								//Position it in the center of the viewport
								width:  preload.width + settings.borderSize*2 +"px",
								height: preload.height + settings.borderSize*2 +"px",
								top:    $(window).height()/2 - preload.height/2 - settings.borderSize +'px',
								left:   $(window).width()/2 - preload.width/2 - settings.borderSize +'px'
							}, settings.speed, 0, function () {
								//Bring in the upcoming image
								$("#g-image")
									//Swap out image sources
									.attr('src', preload.src)
									
									//Prep for fading in
									.css({ opacity: 0, display: 'block'})
									
									//Fade in the image
									.fadeTo(settings.speed, 1, function () {
										//Breath! Animating is done
										animating = false;
										
										//Change the title
										$("#g-title").text(url.title);
										
										//If the mouse is still over the box,
										//Bring in the new image title
										if (hovering) $("#g-title-wrapper")
											.css({ opacity: 0, display: 'block'})
											.fadeTo(settings.speed, 1, function(){ fixIEFilters(this); });
									});
							});
					}).attr('src', url.href)
			});
	};
	
	//Fades out and removes the gallery components
	function close () {
		$(document).unbind('keyup', handleKeyboard);
		$("#gallerize-components").fadeOut(settings.speed, function() {
			$(this).remove();
		});
	};
	
	//Keeps the image centered in the viewport
	$(window).resize(function() {					  
		var imgw = $("#g-image").width();
		var imgh = $("#g-image").height();
		
		$("#g-wrapper").css({
			top:  $(window).height()/2 - imgh/2 - settings.borderSize +'px',
			left: $(window).width()/2 - imgw/2 - settings.borderSize +'px'
		});
	});
	
	//Resizes an image if it's too big for the viewport
	function setMaxDimensions (img) {
		var winw = $(window).width() - settings.borderSize*2 - 40;
		var winh = $(window).height() - settings.borderSize*2 - 40;
		var neww = img.width;
		var newh = img.height;
		
		if (neww > winw) {
			neww = winw;
			newh = neww * img.height / img.width;
		}
		
		if (newh > winh) {
			newh = winh;
			neww = newh * img.width / img.height;
		}
		
		img.width = neww;
		img.height = newh;
		
		return img;
	};
	
	//Removes IE filters after opacity transitions
	//This restores ClearType and PNG smoothing
	function fixIEFilters (obj) {
		if (jQuery.browser.msie)
			$(obj).get(0).style.removeAttribute('filter');
	};
	
	//Function for handling keyboard events
	function handleKeyboard (e) {
		switch(e.keyCode){
			case 37:
				if (current == 0) return;
				loadImage(imgURLs[current - 1]);
				break;
			case 39:
				if (current == imgURLs.length - 1) return;
				loadImage(imgURLs[parseInt(current) + 1]); 
				break;
			case 27:
				close();
				break;
		};
	};
	
	//return the jQuery object for further chaining
	return this;
};

//HTML source for the gallery components
var __gallerizeHTMLSource__ =
'<div id="gallerize-components">'
	+'<div id="g-overlay"></div>'
	+'<div id="g-wrapper">'
		+'<div id="g-img-wrapper">'
			+'<img id="g-image" src="site_files/images/fullsize/f_GOZCard.jpg" />'
			+'<div id="g-title-wrapper"><span id="g-title-l"><span id="g-title-r"><span id="g-title"></span></span></span></div>'
		+'</div>'
		+'<a id="g-prev" href="#previous" title="Previous"></a>'
		+'<a id="g-next" href="#next" title="Next"></a>'
		+'<div id="g-tl"></div>'
		+'<div id="g-t"></div>'
		+'<div id="g-tr"></div>'
		+'<div id="g-l"></div>'
		+'<div id="g-r"></div>'
		+'<div id="g-bl"></div>'
		+'<div id="g-b"></div>'
		+'<div id="g-br"></div>'
	+'</div>'
+'</div>';