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

	current_image: null,
	scrolling: false,
	leftThumb: 0,
	rightThumb: 6,
	loading_image: null,
	loadingImage: null,
	loadingImageEvent: null,
	original_play_text: '',
	// Is the slideshow playing?
	is_playing: false,

	initialize: function(images, options){

		this.image_queue = new Array();
		this.image_preloaders = new Array();
		this.thumb_queue = new Array();
		this.desc_queue = new Array();

		this.options = Object.extend({
			img_container: 'box_image',
			thumb_container: 'box_thumbs_overflow',
			desc_container: 'more_info_inner',
			left_button: 'box_nav_left',
			right_button: 'box_nav_right',
			loading_image: '/images/legacy/loader.gif',
			play_button: 'play_slideshow_a',
			change_play_text: 'Pause',
			frame_length: 3
		}, options || {});

		// Turn it in to milliseconds
		this.options.frame_length = this.options.frame_length * 1000;

		image_dim = $(this.options.img_container).getDimensions();

		// Make the thumbs table
		table = document.createElement('table');
		table.border = 0;
		table.cellSpacing = 0;
		table.cellPadding = 0;

		tbody = document.createElement('tbody');
		table.appendChild(tbody);

		tr = document.createElement('tr');
		tbody.appendChild(tr);

		$(this.options.thumb_container).appendChild(table);

		if (images.length - 1 < this.rightThumb){
			this.rightThumb = images.length - 1;
		}

		// Show the loading image
		this.loading_image = document.createElement('img');
		// Set the source
		this.loading_image.src = '/images/legacy/spacer.gif';

		// Set the style
		$(this.loading_image).setStyle({
			background: '#000000 url(' + this.options.loading_image + ') no-repeat center center',
			width: image_dim.width + 'px',
			height: image_dim.height + 'px',
			position: 'absolute',
			zIndex: 11
		});

		$(this.options.img_container).appendChild(this.loading_image);

		// Loop through and add the thumbs
		images.each(function(val, key){

			// Do the thumbs
			td = document.createElement('td');
			tr.appendChild(td);

			// Align the TD
			td.align = 'center';
			td.valign = 'center';

			div = document.createElement('div');
			div.style.width = '100px';

			td.appendChild(div);

			this.desc_queue[key] = val.desc;

			this.thumb_queue[key] = document.createElement('img');
			$(td).addClassName('box_thumbs');
			div.appendChild(this.thumb_queue[key]);

			$(this.thumb_queue[key]).setStyle({border: '2px solid transparent'});
			this.thumb_queue[key].src = val.thumb;

			// Fade it
			$(this.thumb_queue[key]).setOpacity(0.5);

			// On mouseover highlight it
			Event.observe(this.thumb_queue[key], 'mouseover', function (){
				this.setOpacity(1);
			}.bind($(this.thumb_queue[key])));

			// Set it back
			Event.observe(this.thumb_queue[key], 'mouseout', function (thumb){
				// Not the current image?
				if (this.current_image != thumb){
					$(this.thumb_queue[thumb]).setOpacity(0.5);
				}
			}.bind(this, key));

			// On click, change the current slide
			Event.observe(this.thumb_queue[key], 'click', this.changeSlide.bind(this, key, false));

			// Main images

			// Create the image
			this.image_queue[key] = document.createElement('img');
			// Set the source
			this.image_queue[key].src = '/images/legacy/spacer.gif';

			// Preload the image
			this.image_preloaders[key] = new Image();
			this.image_preloaders[key].src = val.image;

			this.image_queue[key].isLoaded = false;

			// Set the style
			$(this.image_queue[key]).setStyle({
				background: 'transparent url(' + val.image + ') no-repeat center center',
				width: image_dim.width + 'px',
				height: image_dim.height + 'px',
				cursor: 'pointer',
				visibility: 'hidden',
				position: 'absolute'
			});

			// For MSIE
			$(this.image_queue[key]).setStyle('cursor', 'hand');

			$(this.options.img_container).appendChild(this.image_queue[key]);

			// Play/Pause the show
			Event.observe($(this.image_queue[key]), 'click', this.toggleShow.bind(this));

			// Add the listeners
			Event.observe(this.image_preloaders[key], 'load', function(){
				this.isLoaded = true;
			}.bind(this.image_queue[key]));

		}.bind(this));

		// Add the event handlers to the left and right buttons
		Event.observe(this.options.left_button, 'click', this.scrollPrev.bind(this));
		Event.observe(this.options.right_button, 'click', this.scrollNext.bind(this));

		// Play button
		Event.observe($(this.options.play_button), 'click', function(event){ this.toggleShow(); Event.stop(event); }.bindAsEventListener(this));

		// Show the first one on load
		this.changeSlide(0, false);

		// Rest it back to 0
		$(this.options.thumb_container).scrollLeft = 0;
	},

	// Play the slideshow
	playShow: function(){

		this.is_playing = true;

		// Change play text?
		if (this.options.change_play_text){

			if (!this.original_play_text){
				this.original_play_text = $(this.options.play_button).innerHTML;
			}

			$(this.options.play_button).update(this.options.change_play_text);

			// ToDo: Add callback option
		}

		// Go to the next one
		this.play_show_timer = setTimeout(this.nextSlide.bind(this), this.options.frame_length);
	},

	// Move to the next slide
	nextSlide: function(){

		// Avoid multiple timeouts - just a failsafe
		if (this.play_show_timer){
			// Clear the previous timeout
			clearTimeout(this.play_show_timer);
			this.play_show_timer = null;
		}

		var next = this.current_image;
		next++;

		// At least one?
		if (next == this.image_queue.length){
			next = 0;
			// Move to the start again
			$(this.options.thumb_container).scrollLeft = 0;
		}

		// Not loaded?
		if (!this.image_queue[next].isLoaded){

			// Show the loading image
			$(this.loading_image).show();

			// If we're already waiting for an image to load, remove the listener as the user must have changed their mind
			if (this.loadingImage !== null){
				Event.stopObserving(this.image_preloaders[this.loadingImage], 'load', this.loadingImageEvent);
			}

			// When the image has loaded, on with the show!
			Event.observe(this.image_preloaders[next], 'load', this.nextSlide.bind(this));
			return;
		}

		// Show the next slide
		this.changeSlide(next, true);

		// Go to the next one
		this.play_show_timer = setTimeout(this.nextSlide.bind(this), this.options.frame_length);
	},

	// Pause the slideshow
	pauseShow: function(){

		this.is_playing = false;

		// Change it back?
		if (this.original_play_text){
			$(this.options.play_button).update(this.original_play_text);

			// ToDo: Add callback
		}

		// Stop it going any further
		clearTimeout(this.play_show_timer);
		this.play_show_timer = null;
	},

	// Play/Pause the slideshow
	toggleShow: function(){

		if (this.is_playing){
			this.pauseShow();
		}
		else {
			this.playShow();
		}

	},

	changeSlide : function(newSlide, showPlaying){

		if (!showPlaying && this.play_show_timer){
			this.pauseShow();
		}

		// Not loaded yet?
		if (!this.image_queue[newSlide].isLoaded){

			$(this.loading_image).show();

			// Remove the listener on the last one
			if (this.loadingImage !== null){
				Event.stopObserving(this.image_preloaders[this.loadingImage], 'load', this.loadingImageEvent);
			}

			// Save the current waiting image event
			this.loadingImageEvent = this.changeSlide.bind(this, newSlide, false);

			// Show it when loaded
			Event.observe(this.image_preloaders[newSlide], 'load', this.loadingImageEvent);

			// Save the current waiting image
			this.loadingImage = newSlide;

			return;
		}

		// We already viewing it?
		if (this.current_image && this.current_image == newSlide){
			return false;
		}

		// Move the thumbnail container along
		if (newSlide >= this.rightThumb){
			this.scrollNext();
		}

		if (newSlide <= this.leftThumb){
			this.scrollPrev();
		}

		noDelay = false;

		reset = function(e){
			e.cancel();
			e.element.setOpacity(1);
			e.element.hide();

			noDelay = true;
		}

		// Cancel previous effect
		Effect.Queues.get('hideSlide').each(reset);
		Effect.Queues.get('showSlide').each(reset);

		if (this.current_image !== null){
			// Set the zIndex on the old one
			this.image_queue[this.current_image].style.zIndex = 10;
		}

		// Make sure the new one's behind
		this.image_queue[newSlide].style.zIndex = 1;

		// Loading image visible?
		if ($(this.loading_image).visible()){

			// Hide the previous image?
			if (this.current_image !== null){
				// Fade the current one
				$(this.image_queue[this.current_image]).hide();
			}

			// Fade the loader image
			Effect.Fade(this.loading_image, {queue: {position: 'end', limit: 2, scope: 'hideSlide'}});
		}
		else if (this.current_image !== null){
			// Fade the current one
			Effect.Fade(this.image_queue[this.current_image], {queue: {position: 'end', limit: 2, scope: 'hideSlide'}});
		}

		// Build the options
		var opt = {
			afterFinish: function (new_img, old_img){

				if (old_img){
					// Reset the zIndex on the old one
					old_img.style.zIndex = 1;
				}

				// Bring the new one to the front for the next fade
				new_img.style.zIndex = 10;

			}.bind(this, this.image_queue[newSlide], this.image_queue[this.current_image])
		};

		$(this.image_queue[newSlide]).setStyle({visibility: 'visible', display: 'none'});

		// Fade it?
		if (!noDelay){
			opt.delay = 0.5;
		}

		opt.queue = {position: 'end', limit: 2, scope: 'showSlide'};

		// Fade in the new one
		Effect.Appear(this.image_queue[newSlide], opt);

		// Outline the current thumbnail
		$(this.thumb_queue[newSlide]).setStyle({border: '2px solid #FFFFFF'});

		// Make it full opacity
		$(this.thumb_queue[newSlide]).setOpacity(1);

		if (this.desc_queue[newSlide]){
			// Update the description box
			$(this.options.desc_container).update(this.desc_queue[newSlide]);
		}

		if (this.current_image !== null){
			// Un-outline the old thumbnail
			$(this.thumb_queue[this.current_image]).setStyle({border: '2px solid transparent'});

			// Make the previous one faded again
			$(this.thumb_queue[this.current_image]).setOpacity(0.5);
		}

		// Update the previous image variable
		this.current_image = newSlide;
	},

	// Scroll right
	scrollNext: function(){

		if (this.scrolling){
			setTimeout(this.scrollNext.bind(this), 400);

			return false;
		}

		if (this.rightThumb !== this.image_queue.length - 1){
			this.leftThumb++;
			this.rightThumb++;
		}

		this.scrolling = true;

		new Effect.SmoothScroll(this.options.thumb_container, {x: 115, afterFinish: function(){
			this.scrolling = false;
		}.bind(this)});
	},

	// Scroll left
	scrollPrev: function(){

		if (this.scrolling){
			setTimeout(this.scrollPrev.bind(this), 400);

			return false;
		}

		if (this.leftThumb !== 0){
			this.leftThumb--;
			this.rightThumb--;
		}

		this.scrolling = true;

		new Effect.SmoothScroll(this.options.thumb_container, {x: -115, afterFinish: function(){
			this.scrolling = false;
		}.bind(this)});
	}
};
// Modified version of Effect.scroll obtained from Scriptacolous wiki
Effect.SmoothScroll = Class.create();
Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), {
  initialize: function(element) {
    this.element = $(element);
  	this.originalLeft = this.element.scrollLeft;
  	this.originalTop = this.element.scrollTop;
    this.options = Object.extend({
      x: 0,
      y: 0,
      afterFinish: null,
      duration: 2.0
    } , arguments[1] || {}  );

    this.start(this.options);
  },

  update: function(position){
    this.element.scrollLeft = this.originalLeft + (this.options.x * position);
    this.element.scrollTop = this.originalTop + (this.options.y * position);

    if (position === 1 && typeof(this.options.afterFinish) == 'function'){
    	this.options.afterFinish();
    }
  }

});
