(function($) {

	// Slideshow Settings
	// TODO: Should these dimensions be passed in the "data" object?
	var THUMB_WIDTH = 75,
		SLIDE_WIDTH = 81,
		IMAGE_WIDTH = 470;

	// The slideshow object is not exposed, but is used internally.
	function Slideshow($container, data) {
		this.$container = $container;

		this.title = data.title;
		this.slides = data.assets;
		this.rootPath = data.rootPath;

		this.idxCurrent = 0;

		this.render();
	};
	Slideshow.prototype = {
		prevSlide: function() {
			return this.activateSlide(this.idxCurrent - 1);
		},
		nextSlide: function() {
			return this.activateSlide(this.idxCurrent + 1);
		},
		handleSlideClick: function(evt) {
			return this.activateSlide($(evt.target).index());
		},
		activateSlide: function(index) {
			// TODO: Use the number "restrict" method when it is available.
			// this.idxCurrent = index.restrict(0, this.slides.length - 1);
			this.idxCurrent = Math.max(0, Math.min(index, this.slides.length - 1));

			var slide = this.slides[this.idxCurrent];

			// Update the image url, progress, copyright, and abstract
			this.$image.attr('src', slide.image_path);
			this.$progress.text(this.idxCurrent + 1);
			this.$copyright.text(slide.copyright);
			this.$abstract.text(slide['abstract']); // "abstract" is a reserved word in javascript so we have to reference it this way

			// Enable/Disable the prev/next buttons if we are at the start/end
			this.$next.toggleClass('disabled', this.idxCurrent >= this.slides.length - 1);
			this.$prev.toggleClass('disabled', !this.idxCurrent);

			// Move the slides
			this.$slider.animate({ left: -SLIDE_WIDTH * this.idxCurrent });

			return this;
		},
		render: function() {
			var slides = this.slides,
				slide = slides[0],
				len = slides.length,

				// Generate markup for the slideshow
				markup = [
					'<div class="slideshow_control">',
						'<input type="image" class="slideshow_prev disabled" src="', this.rootPath, 'slideshow_backward.gif" title="Previous Image" />',
						'<input type="image" class="slideshow_next" src="', this.rootPath, 'slideshow_forward.gif" title="Next Image" />',
						'<div class="slideshow_slides">',
							'<div class="slideshow_slider">'
				];

			// TODO: Use the array "map" method when we have it available:
			// slides.map(function(slide) { return '<img src="' + getThumbnailUrl(slide) + '" />'; }).join('')
			for(var i = 0; i < len; i++) {
				markup.push(
					'<img src="', slides[i].thumbnail_path, '" onload="jQuery(this).padTo(75, 56);" />',
				);
			}

			markup.push('</div>',
						'<div class="slideshow_highlight"/>',
					'</div>',
				'</div>',
				'<div class="slideshow_current">',
					'<img src="', slide.image_path, '" alt="slideshow image" />',
					'<div class="slideshow_caption">',
						'Viewing <span class="slideshow_progress">1</span> of ', len, ' | &copy; <span class="slideshow_copyright">', slide.copyright, '</span>',
					'</div>',
					'<div class="slideshow_abstract">', slide['abstract'], '</div>',
				'</div>'
			);

			// Joing the markup, jQuery-fy, add some events, and append to the page
			$(markup.join(''))
				.find('div.slideshow_slides')
					.delegate('img', 'click', $.proxy(this, 'handleSlideClick'))
				.end()
				.appendTo(this.$container);

			// Get references to elements we'll use again and add some events
			this.$next = this.$container.find('input.slideshow_next')
				.click($.proxy(this, 'nextSlide'));
			this.$prev = this.$container.find('input.slideshow_prev')
				.click($.proxy(this, 'prevSlide'));
			this.$slider = this.$container.find('div.slideshow_slider')
				.css('width', SLIDE_WIDTH * len);
			this.$image = this.$container.find('.slideshow_current img');
			this.$progress = this.$container.find('span.slideshow_progress');
			this.$copyright = this.$container.find('span.slideshow_copyright');
			this.$abstract = this.$container.find('div.slideshow_abstract');

			return this;
		}
	};


	$.fn.acSlideshow = function(data) {
		// Create and initialize the slideshow
		new Slideshow(this, data);

		// I Am that I Am
		return this;
	};

	// This little plugin is used to pad images to ensure that they take up the
	// proper amount of space on the page.  If the image is smaller than the provided
	// dimensions the we add padding to compensate.
	$.fn.padTo = function(width, height) {
		return this.each(function(){
			var dW = width - this.width,
				dH = height - this.height;
				if(dW > 0) {
					$(this).css({
						paddingLeft: Math.ceil(dW / 2),
						paddingRight: Math.floor(dW / 2)
					});
				}
				if(dH > 0) {
					$(this).css({
						paddingTop: Math.ceil(dH / 2),
						paddingBottom: Math.floor(dH / 2)
					});
				}
		});
	};

})(jQuery);