
var FORWARD = 1;
var BACKWARD = -1;
var SlideshowPhoto = null;
var SlideshowNextPage = null;
var SlideshowPreviousPage = null;

var Slideshow = new Class(
{
	photosPerPage: 10,
	
	twiddle: 0,
	currentIndex: NaN,
	currentPage: NaN,
	tracker: { },
	width: NaN,
	height: NaN,
	
	initialize: function(base_path, photos)
	{
		this.element = $('slideshow');
		this.textBox = $('slideshow_text');
		this.popup = $('slideshow_thumb_popup');
		this.popup.image = this.popup.getElement("img.preview");
		this.popup.container = this.popup.getElement(".container");
		this.width = this.element.getWidth();
		this.height = this.element.getHeight();
		this.base_path = base_path;
		this.photos = photos;		
		this.setupContainer();
		this.preloadPhotos();
		this.showPage(0);
		this.showPhoto(0);
		SlideshowPhoto = this.showPhoto.bind(this);
		SlideshowNextPage = this.nextPage.bind(this);
		SlideshowPreviousPage = this.previousPage.bind(this);
	},
	
	preloadPhotos: function()
	{
		var me = this;
		function loadImage(index)
		{
			if(index >= me.photos.length) { return; }
			var photo = Asset.image(me.base_path + me.photos[index].url, 
			{
				onload: function()
				{
					loadImage(index + 1);
				}
			});
		}
		
		loadImage(0);
	},
	
	nextPage: function()
	{
		var lastPage = Math.ceil(this.photos.length / 10.0) - 1;
		if(this.currentPage < lastPage)
			this.showPage(this.currentPage + 1);
	},
	
	previousPage: function()
	{
		if(this.currentPage > 0)
			this.showPage(this.currentPage - 1);
	},
	
	showPage: function(page)
	{
		if(this.currentPage == page) { return; }		
		var direction = null;
		if(this.currentPage < page) { direction = FORWARD; }
		if(this.currentPage > page) { direction = BACKWARD; }
		this.currentPage = page;
		
		// replace photo links
		var startIndex = page * this.photosPerPage;
		var endIndex = Math.min(startIndex + 10, this.photos.length);
		var html = '';
		for(var i=startIndex;i<endIndex;i++)
		{
			var number = i + 1;
			if((""+number).length < 2) { number = "0" + number; }
			if(i != startIndex) { html += " | "; }
			html += 
				'<a class="photo_link" ' + 
				'rev="' + i + '" ' +
				'id="photo_link_' + i + '" ' + 
				'href="javascript:SlideshowPhoto(' + i + ')">' + number + '</a>';
		}		
		
		// remove any leftover page lists
		this.element.getElements(".navigation").each(function(nav)
		{
			if(nav.expired) { nav.parentNode.removeChild(nav); }
		})
		
		var existingNav = this.element.getElement(".navigation");
		var container = this.element.getElement(".navigation_container");
		var width = container.getWidth();
		var incomingNav = existingNav.clone();
		existingNav.expired = true;
		incomingNav.style.visibility = "visible";
		incomingNav.style.left = width + "px";
		incomingNav.getElement(".photo_links").innerHTML = 
			'<span class="size_fix">&nbsp;</span>' + 
				html + 
			'<span class="size_fix">&nbsp;</span>';
		container.appendChild(incomingNav);
		if(direction == FORWARD)
		{
			existingNav.tween('left', '0px', -width + "px");
			incomingNav.tween('left', width + 'px', "0px");
		}
		else if(direction == BACKWARD)
		{
			existingNav.tween('left', '0px', width + "px");
			incomingNav.tween('left', -width + 'px', "0px");
		}
		else
		{
			existingNav.style.left = -width + "px";
			incomingNav.style.left = "0px";
		}		
		
		this.addPhotoPreviews();
		this.resetActiveStates();
	},
	
	nextPhoto: function()
	{
		if(this.currentIndex < (this.photos.length - 1))
			this.showPhoto(this.currentIndex + 1);
	},
	
	previousPhoto: function()
	{
		if(this.currentIndex > 0)
			this.showPhoto(this.currentIndex - 1);
	},
	
	showPhoto: function(index)
	{
		if(this.currentIndex == index) { return; }
		
		// switch to the right page for this photo
		this.showPage(Math.floor(index / this.photosPerPage));
		
		var direction = null;
		if(this.currentIndex < index) { direction = BACKWARD; }
		if(this.currentIndex > index) { direction = FORWARD; }
		this.currentIndex = index;
		var caption = this.photos[index].caption;
		var url = this.base_path + this.photos[index].url;
		this.resetActiveStates();
		
		// track the current image, and display it when ready
		this.trackImage(url, function()
		{
			this.swapLayers(url, caption, direction);			
		}
		.bind(this));
		
		// track the next image (i.e. pre-load), and do nothing for now
		if((index+1) < this.photos.length)
			this.trackImage(this.base_path + this.photos[index + 1].url, $empty);
	},	
	
	addPhotoPreviews: function()
	{		
		var me = this;
		var width = me.popup.container.getWidth();
		var height = me.popup.container.getHeight();
		me.element.getElements(".photo_link").each(function(link)
		{						
			var photo = me.photos[link.getAttribute('rev')];
			var url = me.base_path + photo.url;
			link.onmouseover = function()
			{
				if(link.hasClass('active')) { return; }
				link.waiting = true;
				var loadImage = new Asset.image(url, 
				{
					onload: function()
					{
						if(link.waiting && !link.hasClass('active'))
						{
							var size = me.fitToSize(loadImage.width, loadImage.height, width, height);
							me.popup.image.src = loadImage.src;
							me.popup.image.setStyles(
							{
								left: Math.floor((width - size.width) / 2) + "px",
								top: Math.floor((height - size.height) / 2) + "px",
								width: size.width + "px",
								height: size.height + "px"
							})
							me.popup.style.visibility = "visible";
							me.popup.style.left = link.offsetLeft + "px";
						}
					}
				});
			};
			
			link.onmouseout = function()
			{
				me.popup.style.visibility = "hidden";
				link.waiting = false;
			}
		});
	},
	
	resetActiveStates: function()
	{
		// active photo link
		var currentId = 'photo_link_' + this.currentIndex;		
		$$("#slideshow .photo_links a").each(function(link)
		{		
			if(link.id == currentId)
			{
				link.addClass("active");
				if(link.onmouseout) { link.onmouseout(); }
			}
			else
			{
				link.removeClass("active");
			}
		});
		
		// last && first page
		var lastPage = Math.ceil(this.photos.length / 10.0) - 1;
		this.element.removeClass("last_page");
		this.element.removeClass("first_page");
		if(this.currentPage == lastPage) { this.element.addClass("last_page"); }
		if(this.currentPage == 0)        { this.element.addClass("first_page"); }
	},
	
	trackImage: function(url, callback)
	{
		if(this.tracker[url] && this.tracker[url].loaded)
		{
			callback();
		}		
		else if(this.tracker[url])
		{
			this.tracker[url].callbacks.push(callback);
		}
		else
		{
			this.tracker[url] = { loaded: false, callbacks: [ callback ] };
			var me = this;
			var asset = new Asset.image(url,
			{
				onload: function()
				{
					me.tracker[url].loaded = true;
					me.tracker[url].callbacks.each(function(currentCallback)
					{
						currentCallback();
					});
				}
			});
		}
	},
	
	swapLayers: function(url, caption, direction)
	{
		var me = this;
		var back = this.backLayer();
		var front = this.frontLayer();
		var image = new Asset.image(url, 
		{
			onload: function() 
			{ 
				var size = me.fitToSize(image.width, image.height, me.width, me.height);
				
				// set the new size and position
				back.image.setStyles(
				{ 
					left: Math.floor((me.width - size.width) / 2) + "px",
					top: Math.floor((me.height - size.height) / 2) + "px",					
					width: size.width + "px", 
					height: size.height + "px" 
				});
				
				// flip the visible layers
				me.twiddle = 1 - me.twiddle;
				back.image.src = image.src;
				
				if(!direction)
				{
					front.style.left = me.width + "px";
					back.style.left = "0px";
				}
				else if(direction == FORWARD)
				{	
					back.tween.start('left', -me.width + "px", "0px");
					front.tween.start('left', "0px", me.width + "px");
				}
				else // direction == BACKWARD
 				{
					back.tween.start('left', me.width + "px", "0px");
					front.tween.start('left', "0px", -me.width + "px");
				}
				
				// display the new image caption
				back.image.alt = caption;
				me.textBox.innerHTML = caption;
			}  
		});
	},
	
	frontLayer: function()
	{
		return this.layers[this.twiddle];
	},
	
	backLayer: function()
	{
		return this.layers[1 - this.twiddle];
	},
	
	setupContainer: function()
	{
		this.layers = [ $('slideshow_layer_a'), $('slideshow_layer_b') ];
		this.layers.each(function(layer)
		{
			layer.image = layer.getElement("img");
			layer.set('tween', 
			{
				link: 'cancel'
			});
			layer.tween = layer.get('tween');
		})
				
		this.element.getElement(".backdrop").setOpacity(0.6);
		var next = $("slideshow_next");
		var nextImage = $("slideshow_next_image");
		var previous = $("slideshow_previous");		
		var previousImage = $("slideshow_previous_image");
		next.onclick = this.nextPhoto.bind(this);
		previous.onclick = this.previousPhoto.bind(this);
		
		// show & hide the next / previous buttons
		var width = next.getWidth();
		next.onmouseover = function() { nextImage.tween('right', -width + 'px', '0px'); }
		next.onmouseout = function() { nextImage.tween('right', '0px', -width + 'px'); }
		previous.onmouseover = function() { previousImage.tween('left', -width + 'px', '0px'); }
		previous.onmouseout = function() { previousImage.tween('left', '0px', -width + 'px'); }
	},
	
	fitToSize: function(width, height, maxWidth, maxHeight)
	{
		var newWidth = maxWidth;
		var newHeight = Math.floor((newWidth / width) * height);
		if(newHeight > maxHeight)
		{			
			newHeight = maxHeight;
			newWidth = Math.floor((newHeight / height) * width);
		}	
		return { width: newWidth, height: newHeight };
	}
	
});
