var PRELOAD_IMAGE = '/_images/icons/loader-white.gif';
var IMAGE_WIDTH = 190;
var launchingGallery = false;
var openingImage = false;

Event.observe(window, 'load', function() {

	var galleryList = $$('#gallery-image-list a', '#gallery-video-list a', '.gallery-image');
	for(var i = 0; i < galleryList.length; i++) {
		new GalleryLauncher(galleryList[i]);
	}

	if(window.location.hash.toString().length > 1) {
		var launcher = new GalleryLauncher();
		launcher.launchGalleryFromHash();
	}

	// preload loading image
	var image = new Image();
	image.src = PRELOAD_IMAGE;
});



var GalleryLauncher = Class.create();
GalleryLauncher.prototype = {

	initialize: function(element) {

		if(element) {

			this.element = element;
			this.type = 'image';
			
			if(element.className.indexOf('video') >= 0) {
				this.type = 'video';
				this.setVideoId();
			} else if(element.className.indexOf('flash') >= 0) {
				this.type = 'flash';
				this.setFlashDimensions();
			}

			this.setAssetPath();

			Event.observe(this.element, 'click', this.launchGallery.bind(this));
		}
	},

	launchGallery: function(e, assetPath, assetCaption) {
	
		// add a class to the body so we can hide the primary nav (IE fix)
		$(document.body).addClassName('gallery-open');
		
		if($('container')) new Effect.ScrollTo($('container'));

		var requestUrl = this.getGalleryURL(e);
		new Ajax.Request(requestUrl + '?asset=' + this.asset_path, {
			method: 'get',
			onSuccess: function(transport) {

				new Insertion.Top('container', transport.responseText);

				$('gallery-overlay-close').onclick = function() {

					this.toggleHeading();

					if($('gallery-video-container')) $('gallery-video-container').remove();

					Effect.BlindUp('gallery-overlay', {
						duration: 2,
						afterFinish: function() {

							$('gallery-overlay').remove();
							
							new Effect.Fade('gallery-overlay-container', { 
									duration: 0.5, 
									afterFinish: function() {
										// remove class from the body to unhide primary nav (IE fix)
										$(document.body).removeClassName('gallery-open');
										
										$('gallery-overlay-container').remove();
									} 
							});

							launchingGallery = false;
						}
					});

					window.location.hash = '#';
				}.bind(this);
				
				Effect.Appear('gallery-overlay-container', {
					duration: 0.5,
					to: 0.8,
					afterFinish: function() {
						Effect.BlindDown('gallery-overlay', {
		
							duration: 2,
							afterFinish: function() {
		
								this.attachThumbnailLinks();
								new GalleryScroller('gallery-thumbs', 'gallery-overlay-right', 'gallery-overlay-left', { speed: 0.7, openedImage: this.getOpenedImage(), galleryNavId: 'gallery-overlay-nav' });
		
								this.toggleHeading();
								this.insertAsset(assetPath);
							}.bind(this)
						});					
					}.bind(this)
				});


			}.bind(this)
		});

		Event.stop(e);
	},

	launchGalleryFromHash: function() {

		var hash = new String(window.location.hash);
		if(hash.indexOf('video/') >= 0) {
			this.type = 'video';
			this.launchGallery('', hash.substring(7));
		} else if(hash.indexOf('swf') >= 0) {
			this.type = 'flash';
			this.launchGallery('', hash.substring(3));
		} else {
			this.type = 'image';
			this.launchGallery('', ASSET_PATH + hash.replace('#', ''));
		}
	},

	insertAsset: function(assetPath, caption) {

		if(this.type == 'video') {

			assetPath = assetPath ? assetPath : this.video_id;

			if($('gallery-video-container')) $('gallery-video-container').remove();
			new Insertion.Before('gallery-image-preloader', '' +
				'<div id="gallery-video-container">' +
				'	<object width="604" height="360">' +
				'		<param name="movie" value="http://www.youtube.com/v/' + assetPath + '&autoplay=1"></param>' +
				'		<param name="wmode" value="transparent"></param>' +
				'		<embed src="http://www.youtube.com/v/' + assetPath + '&autoplay=1" type="application/x-shockwave-flash" wmode="transparent" width="604" height="360"></embed>' +
				'	</object>' +
				'</div>'
			);
			$('gallery-image-preloader').remove();

			openingImage = false;
		} else if(this.type == 'flash') {
		
			assetPath = assetPath ? assetPath : this.element.href;
				
			if($('gallery-flash-container')) $('gallery-flash-container').remove();
			new Insertion.Before('gallery-image-preloader', '' +
				'<div id="gallery-flash-container">' +
				'	<object width="' + this.flash_width + '" height="' + this.flash_height + '">' +
				'		<param name="movie" value="' + assetPath + '"></param>' +
				'		<param name="wmode" value="transparent"></param>' +
				'		<embed src="' + assetPath + '" type="application/x-shockwave-flash" wmode="transparent" width="' + this.flash_width + '" height="' + this.flash_height + '"></embed>' +
				'	</object>' +
				'</div>'
			);
			$('gallery-image-preloader').remove();

			openingImage = false;					
		} else {

			assetPath = assetPath ? assetPath : this.element.href;
			caption = caption ? caption : this.caption;

			var imageObj = new Image();
			imageObj.onload = function() {

				$('gallery-image-preloader').remove();
				$('gallery-overlay-image').src = assetPath;
				if(typeof(caption) != 'undefined') $('gallery-overlay-image').alt = caption;

				new Effect.Appear('gallery-overlay-image', {
					duration: 2,
					afterFinish: function() {

						if(typeof(caption) != 'undefined') $('gallery-overlay-caption').innerHTML = caption;
						openingImage = false;
					},
					queue: {position: 'end', scope: 'imageswitchscope', limit: 5}
				});
			}.bind(this);

			imageObj.src = assetPath;
		}

		this.updateHash(assetPath);
	},

	updateHash: function(assetPath) {

		var str = new String(assetPath);

		str = str.replace(window.location.host, '');
		str = str.replace(window.location.protocol, '');
		str = str.replace('/' + ASSET_PATH, '');

		if(this.type == 'video') str = 'video/' + str;

		window.location.hash = str;
	},

	setVideoId: function() {

		if(this.type == 'video') {

			var regex = /youtube.com\/watch\?v=([^\/]{11})/;
			this.video_id = regex.exec(this.element.href)[1];
		}
	},
	
	setFlashDimensions: function() {
		if (this.type == 'flash') {
			var regex = /([0-9]*)x([0-9]*)/;
			this.flash_width = regex.exec(this.element.className)[1];
			this.flash_height = regex.exec(this.element.className)[2];
		}		
	},

	setAssetPath: function() {

		if(this.type == 'video') {

			var image = this.element.down('img');
			var components = image.src.split('/');

			var groupId = components[components.length -2];

			this.asset_path = groupId + '/' + this.video_id;
		} else if(this.type == 'flash') {
		
			this.asset_path = this.element.href;
			this.caption = '';
		} else {

			this.asset_path = this.element.href;
			this.caption = Element.immediateDescendants(this.element)[0].alt;
		}
	},

	attachThumbnailLinks: function() {

		var galleryThumbnails = $('gallery-thumbs-inner');

		if(galleryThumbnails) {

			galleryLinks = galleryThumbnails.getElementsByTagName('a');
			for(var i = 0; i < galleryLinks.length; i++) {

				galleryLinks[i].onclick = function(e) {

					var eventObject = $A(arguments)[1];

					if(!openingImage) {

						openingImage = true;

						galleryLinks = $('gallery-thumbs-inner').getElementsByTagName('a');
						for(var i = 0; i < galleryLinks.length; i++) {

							$(galleryLinks[i]).removeClassName('selected');
						}


						$('gallery-overlay-image').style.display = 'none';
						$('gallery-overlay-caption').innerHTML = '';
						new Insertion.After('gallery-overlay-image', '<img src="' + PRELOAD_IMAGE + '" id="gallery-image-preloader">');


						if(this.type == 'video') {

							var components = eventObject.href.split('/');
							var assetPath = components[components.length -1];
							var caption = '';
						} else {

							var assetPath = eventObject;
							var caption = Element.immediateDescendants(eventObject)[0].alt;
						}

						this.insertAsset(assetPath, caption);

						eventObject.addClassName('selected');
					}

					return false;
				}.bindAsEventListener(this, galleryLinks[i]);
			}
		}
	},

	getOpenedImage: function() {

		var galleryThumbnails = $('gallery-thumbs-inner');
		if(galleryThumbnails) {

			galleryLinks = galleryThumbnails.getElementsByTagName('a');
			for(var i = 0; i < galleryLinks.length; i++) {

				if($(galleryLinks[i]).hasClassName('selected')) {

					return i;
				}
			}
		}
	},

	toggleHeading: function() {

		/* Safari does some strange things with the flash header when the gallery is expanded.
		This function can be called after the blind drops down and before the blind pulls up
		to toggle the visibility of the heading */

		var pageHeadings = document.getElementsByTagName('h2');
		if(pageHeadings && pageHeadings.length > 0) {

			$(pageHeadings[0]).toggle();
		}
	},
	
	getGalleryURL: function(event) {
		var eventElement = Event.element(event);
		
		if(eventElement && eventElement.up('a') && eventElement.up('a').rel) {
			return eval('GALLERY_URL_' + eventElement.up('a').rel);
		} else if(this.type == 'video') {
			return GALLERY_URL_VIDEO 
		} else {
			return GALLERY_URL;
		}
	}
};



/**
 * GalleryScroller Effects class
 *
 * Effects class for scrolling a list of images smoothly and elegantly.
 * Intended for use on elements with overflow set to hidden, that contain a
 * number of images that will be scrolled in to view.
 *
 * Basic usage:
 *  new GalleryScroller('containing-element', 'forward-link', backward-link', { speed: 1.0, openedImageOffset: 0 });
 *
 * @author Chris Blackburn <chrisb@de-construct.com>
 * @version $Id: tags.version.pkg,v 1.0 2007/03/07 15:32:00 cellog Exp $;
 */
var GalleryScroller = Class.create();
GalleryScroller.prototype = {

	initialize: function(element, scrollForwardListener, scrollBackwardListener) {

		this.lastaction = 'forwards';

		this.element = $(element);
		this.scrollForwardListener = $(scrollForwardListener);
		this.scrollBackwardListener = $(scrollBackwardListener);

		this.scrollerWidth = this.getScrollerWidth();

		this.options = Object.extend({
			speed: 1.0,
			openedImageOffset: 0,
			galleryNavId: false
		}, arguments[3] || {});

		this.setup();
		
		this.setInitialNavState();

		this.scrollForwardEvent = this.scrollForward.bindAsEventListener(this);
		this.scrollBackwardEvent = this.scrollBackward.bindAsEventListener(this);

		Event.observe(this.scrollForwardListener, 'click', this.scrollForwardEvent);
		Event.observe(this.scrollBackwardListener, 'click', this.scrollBackwardEvent);

		// Now scroll so the opened image is in focus
		this.scrollForward('e', 'initialImage');
	},

	setup: function() {

		this.innerContainer = $('gallery-thumbs-inner');

	  // Safari chokes if the list items are floated left, so we need to fix
	  // it with some CSS hackery.
		/*if(Prototype.Browser.WebKit) {

			var listItems = this.element.getElementsByTagName('li');
			for(var i = 0; i < listItems.length; i++) {

				listItems[i].addClassName('safari');
			}
		}*/

		if(this.getWidthToScroll('forward')) {

			this.scrollForwardListener.removeClassName('gallery-overlay-end');
		}
	},

	scrollForward: function(event, option) {
		Event.stopObserving(this.scrollBackwardListener, 'click', this.scrollBackwardEvent);

		if(this.scrollerWidth-this.getElementWidth(this.element) > 0) {

		  // Ensure the event for scrolling the other way is being observed.
			Event.observe(this.scrollBackwardListener, 'click', this.scrollBackwardEvent);

		  // Ensure the backward button appears enabled
			this.scrollBackwardListener.removeClassName('gallery-overlay-end');
		}
				
		var offset = 0;
		
		if(option == 'initialImage' && this.scrollerWidth-this.getElementWidth(this.element) > 0) {
		
			offset = this.getInitialImageOffset();
						
			if(offset == 0) {
				this.scrollBackwardListener.addClassName('gallery-overlay-end');
			}
		} else if(this.scrollerWidth > this.getElementWidth(this.element)) {

			offset = this.getWidthToScroll('forward');
		}
		
		var negativeOffset = parseFloat('-' + offset);
		var scrollSpeed = this.options.speed;

		if((negativeOffset+this.getLeft()) < parseFloat('-' + (this.scrollerWidth-this.getElementWidth(this.element)))) {

		  	this.lastaction = 'backwards';

		  // There aren't enough fresh images to scroll in a whole new view, so
		  // adjust the amount we need to scroll and the speed accordingly.
			negativeOffset = (this.getLeft()-(this.getLeft()*2)) - (this.scrollerWidth-this.getElementWidth(this.element)+2);
			scrollSpeed = (this.options.speed / 100) * (((negativeOffset-(negativeOffset*2)) / this.getElementWidth(this.element)) * 100);

		  // Show the disabled state for the forward button
			this.scrollForwardListener.addClassName('gallery-overlay-end');
		}
				
		if(!isNaN(negativeOffset)) {

			new Effect.Move(this.innerContainer, {
								x: negativeOffset,
								y: 0,
								transition: Effect.Transitions.sinoidal,
								duration: scrollSpeed,
								queue: {position:'end', scope: 'galleryscope', limit:1}
			});
		}

		setTimeout(this.observeForwardClick.bindAsEventListener(this), this.options.speed * 100);

		if(typeof(event) == 'object') {

			Event.stop(event);
		}
	},

	scrollBackward: function(event) {
		Event.stopObserving(this.scrollBackwardListener, 'click', this.scrollBackwardEvent);

	  // Ensure the event for scrolling the other way is being observed.
		Event.observe(this.scrollForwardListener, 'click', this.scrollForwardEvent);

	  // Ensure the forward button appears enabled
		this.scrollForwardListener.removeClassName('gallery-overlay-end');

		var offset = this.getWidthToScroll('backward');
		var scrollSpeed = this.options.speed;

		if(this.getLeft()+offset >= 0) {

			this.lastaction = 'forwards';

		  // There aren't enough fresh images to scroll in a whole new view, so
		  // adjust the amount we need to scroll and the speed accordingly.
			offset = offset - (this.getLeft() + offset);
			scrollSpeed = (this.options.speed / 100) * ((offset / this.getElementWidth(this.element)) * 100);

		  // Show the disabled state for the backward button
			this.scrollBackwardListener.addClassName('gallery-overlay-end');
		}
		
		new Effect.Move(this.innerContainer, {
							x: offset,
							y: 0,
							transition: Effect.Transitions.sinoidal,
							duration: scrollSpeed,
							queue: {position:'end', scope: 'galleryscope', limit:1}
		});

		setTimeout(this.observeBackwardClick.bindAsEventListener(this), this.options.speed * 100);

		if(typeof(event) == 'object') {

			Event.stop(event);
		}
	},
	
	setInitialNavState: function() {
		var scrollerWidth = this.getScrollerWidth();
		var viewableWidth = this.getElementWidth(this.element);
		
		if(scrollerWidth < viewableWidth) {
			if($(this.options.galleryNavId)) {
				$(this.options.galleryNavId).hide();
			}
		}
	},

	getScrollerWidth: function() {

	  // Loop through the content of the image list, getting the width
	  // of each and adding it to the total.
		var images = this.element.getElementsByTagName('li');
		var width = 0;
		for(var i = 0; i < images.length; i++) {

			width += this.getElementWidth(images[i]);
		}

		return width +1;
	},

	getLeft: function() {

		var left = parseFloat($(this.innerContainer).getStyle('left'));
		if(isNaN(left)) {

			left = 0;
		}

		return left;
	},

	getEdgedImage: function() {

		var left = this.getLeft();
		var images = this.element.getElementsByTagName('li');
		var width = 0;
		var leftVal = left;


		if(this.getLeft() == 0) {

			return 0;
		} else if(this.getLeft() == this.scrollerWidth) {

			return images.length;
		}

		if(this.lastaction == 'backwards') {

			leftVal = left - this.getElementWidth(this.element);
		}

		for(var i = 0; i < images.length; i++) {

			width += this.getElementWidth(images[i]);
			if(parseFloat('-' + width) < leftVal) {

				return i;
			}
		}

		return images.length;
	},

	getWidthToScroll: function(direction) {

		var images = this.element.getElementsByTagName('li');
		var width = 0;
								
		return this.getElementWidth(this.element) -2;

		/*if(direction == 'forward') {
		
			if(this.lastaction == 'backwards') {

				return this.getElementWidth(this.element);
			} else {

			  // Loop through the images from the current offset, working out
			  // which one is the first that is hanging off the edge of the
			  // screen.
			  	var width = 0;
				for(var i = this.getEdgedImage(); i < images.length; i++) {

					width += this.getElementWidth(images[i]);
					if(width > this.getElementWidth(this.element)) {

						return width - this.getElementWidth(images[i]);
					}
				}
			}
		} else if(direction == 'backward') {
		
			if(this.lastaction == 'forwards') {

				return this.getElementWidth(this.element);
			} else {
			
				for(var i = this.getEdgedImage()-1; i > 0; i--) {

					width += IMAGE_WIDTH;
					if(width > this.getElementWidth(this.element)) {

						return width - IMAGE_WIDTH;
					}
				}
				
				return width - this.getElementWidth(images[i]);
			}
		}

		return false;*/
	},

	getInitialImageOffset: function() {

		var images = this.element.getElementsByTagName('li');
		var width = 0;
		for(var i = 0; i < this.options.openedImage; i++) {

			width += this.getElementWidth(images[i]);
		}

		return width;
	},

	getElementWidth: function(element) {
	
		return Element.getWidth(element);
	},

	observeBackwardClick: function() {

		Event.observe(this.scrollBackwardListener, 'click', this.scrollBackwardEvent);
	},

	observeForwardClick: function() {

		Event.observe(this.scrollForwardListener, 'click', this.scrollForwardEvent);
	}
}