(function($){  

	$.fn.extend({

		gallerize: function(options) {

			var options = $.extend({}, $.fn.gallerize.defaults, options);
				
			function preload_images(image_list) { // Preload the images
				var images = [];
				for (var i = 0; i < image_list.length; i++) {
					var im = $('<img />');
					im.attr('src', jQuery(image_list[i]).attr('href'));
					images.push($(im));
				}
				return images;
			}
				
			function change_image(clicked_thumb, main_div, main_img) { // Switch to an image
				$(clicked_thumb).parents('ul:first').find('img').removeClass('current');
				$(clicked_thumb).addClass('current');
				if (! ($.browser.msie && ($.browser.version < 7)) ) {
					main_div.css({'background-image': 'url("' + $(clicked_thumb).parent('a').attr('href') + '")'});
				}
				main_img.stop().fadeTo(options.fade, 0, 
					function(){
						main_img.attr('src', $(clicked_thumb).parent('a').attr('href'));
						main_img.fadeTo(options.fade, 1);
					}
				);
				// main_div.find('div.gallerize-caption').animate({bottom: 0}, options.fade / 4, function(){
					main_div.find('div.gallerize-caption').html($(clicked_thumb).parents('li:first').children('div.caption').html());
					// if ( ! ($.browser.msie && ($(clicked_thumb).parents('li:first').children('div.caption').html() == '' || $(clicked_thumb).parents('li:first').children('div.caption').html() == null)))
					// main_div.find('div.gallerize-caption').animate({bottom: main_div.find('div.gallerize-caption').outerHeight() + 'px'}, options.fade / 4);
				// });
			}
			
			function next_image(e) {
				var top_ul = $(e.data.top_ul);
				var current_image = top_ul.find('img.current');
				var first_image = top_ul.find('img:first');
				var last_image = top_ul.find('img:last');
				var next_image = current_image.parents('li:first').next().find('img:first');
				if (!last_image.hasClass('current')) {
					_this.animate({'left': parseInt(_this.css('left')) - next_image.outerWidth() - parseInt(next_image.parents('li:first').css('margin-right')) - parseInt(next_image.parents('li:first').css('margin-left')) });
					change_image(next_image, e.data.main_div, e.data.main_img);
				} else {
					_this.animate({'left': get_thumbnail_strip_left_offset()})
					change_image(first_image, e.data.main_div, e.data.main_img)
				}
				if (!e.isDefaultPrevented()) e.preventDefault();
			}
			
			function prev_image(e) {
				var top_ul = $(e.data.top_ul);
				var current_image = top_ul.find('img.current');
				var first_image = top_ul.find('img:first');
				var last_image = top_ul.find('img:last');
				var prev_image = current_image.parents('li:first').prev().find('img:first');
				if (!first_image.hasClass('current')) {
					_this.animate({'left': parseInt(_this.css('left')) + prev_image.outerWidth() + parseInt(prev_image.parents('li:first').css('margin-right')) + parseInt(prev_image.parents('li:first').css('margin-left'))});
					change_image(prev_image, e.data.main_div, e.data.main_img);
				}
				e.preventDefault();
			}
			
			// Calculate the left offset depending on the options.thumbnail_strip_start setting
			function get_thumbnail_strip_left_offset() {
				if (options.thumbnail_strip_start == 'center') 
					return (options.width - parseInt(_this.find('li:first').width())) / 2;
				else 
					return 0;
			}

			return this.each(function() {  
				_this = jQuery(this);
				var main_div, main_img, slideshowing;
           
				// where do we insert the main div? Before or after the main ul element?
				if (options.main_img_position == 'before') main_div = _this.before('<div class="gallerize-main"></div>').prev();
				else main_div = _this.after('<div class="gallerize-main"></div>').prev();
				main_div.append('<img>');
				main_img = main_div.children('img');
				
				/* Setting up the first caption, if it's available */
				main_div.append('<div class="gallerize-caption">' + _this.find('div.caption').html() + '</div>');
				$(main_div).find('.gallerize-caption').css({'position':'relative', 'bottom': $(main_div).find('div.gallerize-caption').outerHeight() });
				
				var images = preload_images(_this.children('li').children('a'));
				main_div.css({'width': options.width + 'px', 'height': options.height + 'px', 'background-position': options.align + ' ' + options.valign });
				main_img.attr('src', _this.find('li:first a:first').attr('href'));
				_this.find('li:first img').addClass('current');
				
				$(main_img).load(function(){ // This is needed in order to get ALWAYS the real outerWidth and outerHeight
					/* Horizontally aligning the image using left margin */
					var margin = 0;
					if (options.align == 'center') {
						margin = (options.width - main_img.outerWidth()) / 2;
					} else if (options.align == 'right') {
						margin = (options.width - main_img.outerWidth());
					}
					main_img.css('margin-left', margin + 'px');

					/* Vertically aligning the image using top margin */
					margin = 0;
					if (options.valign == 'center') {
						margin = (options.height - main_img.outerHeight()) / 2;
					} else if (options.valign == 'bottom') {
						margin = (options.height - main_img.outerHeight());
					}
					main_img.css('margin-top', margin + 'px');
				});
				
				/* Creating a sliding thumbnail strip */
				_this.wrap('<div class="thumbnail-strip"></div>');
				var thumbnail_div = _this.parent();
				if (options.thumbnail_strip_height == 'default') {
					thumbnail_div.css('height', _this.find('li').outerHeight() + parseInt(_this.find('li').css('margin-top')) + parseInt(_this.find('li').css('margin-bottom') ));
				} else {
					thumbnail_div.css('height', options.thumbnail_strip_height);
				}
				/* Making the thumbnail strip slideable */
				_this.parent().css('position','relative');
				_this.css('position','absolute');
				_this.css('width', 4000);
				
				// check where the thumbnails should start
				_this.css('left', get_thumbnail_strip_left_offset);
				
				/* We need to reset the margins of the ul, as the thumbnail-strip wrapper should take care of the left and right margins */
				_this.css('margin-left',0);
				_this.css('margin-right',0);
				
				/* Bind events */
				/* Bind a click on a thumbnail */
				$('ul.gallerize li a').bind('click', function(e){
					change_image($(e.target), main_div, main_img);
					_this.animate({'left': _this.offset().left - $(this).offset().left + parseInt($(this).parent().css('margin-left')) + get_thumbnail_strip_left_offset() });

					e.preventDefault();
				})
				
				/* Bind a click for the previous and next buttons */
				jQuery(options.next_image).bind('click', {top_ul: this, main_div: main_div, main_img: main_img}, next_image);
				
				jQuery(options.prev_image).bind('click', {top_ul: this, main_div: main_div, main_img: main_img}, prev_image);
				
				/* Bind a click for start/stop slideshow */
				jQuery(options.slideshow).bind('click', {top_ul: this, main_div: main_div, main_img: main_img, slideshowing: true}, function(e){
					if (slideshowing) {
						// stop slideshow
						clearInterval(slideshowing);
						e.slideshowing = slideshowing = false;
						$(options.slideshow).removeClass(options.slideshow_pause_class).addClass(options.slideshow_play_class);
					} else {
						slideshowing = setInterval(function(){next_image(e)}, options.timer);
						$(options.slideshow).removeClass(options.slideshow_play_class).addClass(options.slideshow_pause_class);
					}
					e.preventDefault();
				});
				
				return this;
				
			});
    }
  });

	$.fn.gallerize.defaults = {
		main_img_position: 'before',
		width: 640,
		height: 480,
		
		/* possible values: top, bottom, center */
		valign: 'center',
		
		/* possible values: left, right, middle; if you're using text-align to align the image, leave this to the default - 'left' */
		align: 'left',
		
		fade: 1000,
		
		// jQuery selector to bind to the next image action
		next_image: '.next-image',
		
		// jQuery selector to bind to the previous image action
		prev_image: '.prev-image',
		
		// jQuery selector for the slideshow toggle button, class 'play' is added when the slideshow is running, class 'stop' is added when the slideshow is not running
		slideshow: '.slideshow',
		
		slideshow_play_class: 'slideshow-play',
		
		slideshow_pause_class: 'slideshow-pause',
		
		// if set to 'default' we'll calculate the height of the thumbnail strip based on the formula - li height + margin-top + margin-bottom
		thumbnail_strip_height: 'default',
		
		// possible values are 'left' and 'center'; if set to 'center' the first (current) thumbnail will be in the middle of the strip 
		thumbnail_strip_start: 'center',
		
		// How many milliseconds should a picture be kept when a slideshow is running
		timer: 2500
	}
})(jQuery);