/**
 * This class requires the prototype javascript library version 1.6 or above.
 */

	var ui_slider = Class.create({
		
		initialize: function(element, options) 
		{
			this.name = name;
			this.options = options;
			this.container = $(element);
			
			if (this.options.links == undefined) {
				this.options.links = {};
			}
			if (this.options.buttons == undefined) {
				this.options.buttons = {};
			}
			if (this.options.count == undefined) {
				this.options.count = {};
			}
			if (this.options.selectElements == undefined) {
				this.options.selectElements = 'li';
			}
			
			// Get the cells from the container.
			this.cells = this.container.select( this.options.selectElements );
				
			this.slider = { cellCount:this.cells.length,
				 			 currentCellNumber:1,
							 rebuildLinks:true,
							 playSlideshow:false
							};			
			//
			//Set up some valueable setting for the gallery.
			//
			
			//Effect.
			if (options.effect != undefined && options.effect == 'slide') {
				this.options.effect = options.effect;
				if (options.slideDirection != undefined && (options.slideDirection == 'random' || options.slideDirection == 'up' || options.slideDirection == 'down' || options.slideDirection == 'left' || options.slideDirection == 'right')) {
					this.options.slideDirection = options.slideDirection;
				} else {
					this.options.slideDirection = 'left';
				}
			} else {
				this.options.effect = 'fade';
			}
			
			//Width.
			if (options.width != undefined && typeof(options.width) == 'number') {
				this.options.width = options.width;
			} else {
				this.options.width = 400;
			}
			//Height.
			if (options.height != undefined && typeof(options.height) == 'number') {
				this.options.height = options.height;
			} else {
				this.options.height = 300;
			}
			
			//Image links number.
			if (options.links.number != undefined && typeof(options.links.number) == 'number') {
				this.slider.linksNumber = options.links.number;
			} else {
				this.slider.linksNumber = 7;
			}
			
			
			this.slider.rebuildLinks = true;
			if (this.slider.linksNumber > this.slider.cellCount) {
				this.slider.linksNumber = this.slider.cellCount;
				this.slider.linksPadding = 0;
				//this.slider.rebuildLinks = false;
			} else {
				//How many links to show either side of the current link.
				if (this.slider.linksNumber%2) {
					//The number of links is odd. Don't change it.
				} else {
					//The number of links is even. Make it odd.
					this.slider.linksNumber --;
				}
				if (this.slider.linksNumber < 3) {
					this.slider.linksNumber = 3;
				}
				this.slider.linksPadding = Math.round( (this.slider.linksNumber - 1) / 2 );
			}
			
			//Show buttons.
			if (options.buttons.show != undefined && options.buttons.show == false) {
				this.slider.showButtons = false;
			} else {
				this.slider.showButtons = true;
			}
				
			//Show cell number.
			if (options.count.show != undefined && options.count.show == false) {
				this.slider.showNumber = false;
			} else {
				this.slider.showNumber = true;
			}
			//Show links.
			if (options.links.show != undefined && options.links.show == false) {
				this.slider.showLinks = false;
			} else {
				this.slider.showLinks = true;
			}
			/*	
			//Show the cells as a slide show. Should over ride the default setting. Should also play as a slideshow if no buttons or links are shown.
			if ( (options.slideshow != undefined && options.slideshow == true) || (this.slider.showLinks == false && this.slider.showButtons == false) ) {
				this.slider.playSlideshow = true;
				this.slider.playMode = 'play';
			}
			*/
			this.slider.playSlideshow = true;
			this.slider.playMode = 'play';
			//Slide show duration. Milliseconds.
			if (options.slideshowDuration != undefined && typeof(options.slideshowDuration) == 'number') {
				this.options.slideshowDuration = options.slideshowDuration * 1000;
			} else {
				this.options.slideshowDuration = 5000;
			}
			//Slide show transition duration. Seconds.
			if (options.transitionDuration != undefined && typeof(options.transitionDuration) == 'number') {
				this.options.transitionDuration = options.transitionDuration;
			} else {
				this.options.transitionDuration = 0.5;
			}
			//Start delay.
			if (options.startDelay != undefined && typeof(options.startDelay) == 'number') {
				this.options.startDelay = this.options.startDelay * 1000;
			} else {
				this.options.startDelay = this.options.slideshowDuration;
			}
			
			//Transition duration should not be more than the slideshow duration.
			if (this.options.transitionDuration * 1000 > this.options.slideshowDuration) {
				this.options.transitionDuration = (this.options.slideshowDuration - 500) / 1000;
			}
			//
			//End of setting up valuable settings.
			//
			
			//Save a reference to the specified container element in a 'domElements' object. This is used later to reference many more elements.
			this.domElements = { container:$(element) };
			
			// Set some styles on the container.
			this.container.style.width = this.options.width+'px';
			this.container.style.height = this.options.height+'px';
			this.container.style.position = 'relative';
			this.container.style.overflow = 'hidden';
			// Set some styles on the cells.
			for ( i = 0; i < this.slider.cellCount; i ++ ) {
				cell = this.cells[i];
				cell.style.position = 'absolute';
				cell.style.left = '0px';
				cell.style.top = '0px';
				cell.style.width = this.options.width+'px';
				cell.style.height = this.options.height+'px';
				cell.style.overflow = 'hidden';
				cell.hide();
			}
			
			this.slider.currentCell = this.cells[0];
			this.slider.currentCell.show();
			
			//Start the image gallery slideshow.
			if (this.slider.playSlideshow == true) {
				this.slider.timeout = setTimeout( this.next.bind( this ), this.options.startDelay );
				this.buildUI();
			}
		},
		
		/**
		 * Prints the entire image gallery markup to the screen.
		 */
		buildUI: function()
		{	
			//
			//Create the image number elements.
			//
			
			countStyle = '';
			if (this.slider.showCellNumber == false) {
				countStyle += ' display:none;';
			}
			
			this.domElements.cellCount = new Element('div', { 'class':'ui-slider-cell-number', 'style':countStyle });
			this.domElements.cellCount.update( '1 of ' + this.slider.cellCount );
			this.container.insert( { after : this.domElements.cellCount } );
			
			//
			//Create the cell links.
			//
			
			//Create the links container.
			linksStyle = '';
			if (this.slider.showImageLinks == false) {
				linksStyle += ' display:none;';
			}
			
			this.domElements.cellLinks = new Element('div', { 'class':'ui-slider-links', 'style':linksStyle });
			this.domElements.cellCount.insert( { after : this.domElements.cellLinks } );
			
			//Put in the 'fewer' span.
			this.domElements.cellLinksFewer = new Element('span', { 'class':'ui-slider-links-fewer' });
			this.domElements.cellLinks.update( this.domElements.cellLinksFewer );
			
			for (count = 1; count <= this.cells.length && count <= this.slider.linksNumber; count ++) {
				this.domElements['link_'+count] = new Element('a', { 'class':'ui-slider-links-link', href:'#null' });
				this.domElements['link_'+count].update( count );
				if (count == 1) {
					this.domElements['link_'+count].setAttribute( 'class', 'current');
				}
				//Add an event observer to the element.
				this.domElements['link_'+count].observe('click', this.swapCell.bind(this, count));
				
				//Add the element to the dom.
				if (count == 1) {
					this.domElements.cellLinksFewer.insert( { after : this.domElements['link_'+count] } );
				} else {
					this.domElements['link_'+(count-1)].insert( { after : this.domElements['link_'+count] } );
				}
			}
			
			//Add the 'more' link.
			this.domElements.cellLinksMore = new Element('span', { 'class':'ui-slider-links-more' });
			if (this.slider.linksNumber < this.slider.cellCount) {
				this.domElements.cellLinksMore.update( '...' );
			}
			this.domElements['link_'+this.slider.linksNumber].insert( { after : this.domElements.cellLinksMore } );
			
			//
			//Create the buttons.
			//
			
			buttonsStyle = '';
			if (this.slider.showButtons == false) {
				buttonsStyle += ' display:none;';
			}
			this.domElements.buttons = new Element('div', { 'class':'ui-slider-buttons', 'style':buttonsStyle });
			this.domElements.cellLinks.insert( { after : this.domElements.buttons } );
			//First.
			this.domElements.buttonFirst = new Element('a', { 'href':'#null', 'class':'ui-slider-button-first' });
			this.domElements.buttonFirst.update( '<span>first</span>' );
			this.domElements.buttonFirst.observe('click', this.first.bind(this));
			this.domElements.buttons.update( this.domElements.buttonFirst );
			//Previous.
			this.domElements.buttonPrevious = new Element('a', { 'href':'#null', 'class':'ui-slider-button-previous' });
			this.domElements.buttonPrevious.update( '<span>previous</span>' );
			this.domElements.buttonPrevious.observe('click', this.previous.bind(this));
			this.domElements.buttonFirst.insert( { after : this.domElements.buttonPrevious } );
			//Play / Pause.
			this.domElements.buttonPlay = new Element('a', { 'href':'#null', 'class':'ui-slider-button-play' });
			this.domElements.buttonPlay.update( '<span>pause</span>' );
			this.domElements.buttonPlay.observe('click', this.togglePlayPause.bind(this));
			this.domElements.buttonPrevious.insert( { after : this.domElements.buttonPlay } );
			//Next.
			this.domElements.buttonNext = new Element('a', { 'href':'#null', 'class':'ui-slider-button-next' });
			this.domElements.buttonNext.update( '<span>next</span>' );
			this.domElements.buttonNext.observe('click', this.next.bind(this));
			this.domElements.buttonPlay.insert( { after : this.domElements.buttonNext } );
			//Last.
			this.domElements.buttonLast = new Element('a', { 'href':'#null', 'class':'ui-slider-button-last' });
			this.domElements.buttonLast.update( '<span>last</span>' );
			//Add the 'last' button after the 'next' button.
			this.domElements.buttonLast.observe('click', this.last.bind(this));
			this.domElements.buttonNext.insert( { after : this.domElements.buttonLast } );
			
		},

		/**
		 * Swaps between the current image and another specified image.
		 */
		swapCell: function(cellNumber) 
		{
			if ( cellNumber == this.slider.currentCellNumber ) {
				return;
			}

			//Fade out the old image.
			//this.slider.currentCell.className = 'lower';
			if ( this.options.effect == 'fade' ) {
				new Effect.Fade( this.slider.currentCell, { duration: this.options.transitionDuration } );
			} else if ( this.options.effect == 'slide' ) {
				// Animate the cell off from on screen.
				var slideDirection = this.options.slideDirection;
				if ( this.options.slideDirection == 'random') {
					var dirs = ['left', 'right', 'up', 'down'];
					slideDirection = dirs[Math.floor(Math.random()*4)];
				}
				if ( slideDirection == 'left' || slideDirection == 'right' ) {
					cellMoveX = this.options.width * -1;
					if ( slideDirection == 'right' ) {
						cellMoveX = this.options.width;
					}
					cellMoveY = 0;
				} else if ( slideDirection == 'up' || slideDirection == 'down' ) {
					cellMoveY = this.options.height * -1;
					if ( slideDirection == 'down' ) {
						cellMoveY = this.options.height;
					}
					cellMoveX = 0;
				}
				new Effect.Move( this.slider.currentCell, { x:cellMoveX, y:cellMoveY, mode:'absolute', duration:this.options.transitionDuration, transition:Effect.Transitions.sinoidal } );
			}

			// Update the reference for the current cell.
			this.slider.currentCell = this.cells[cellNumber-1];
			this.slider.currentCellNumber = cellNumber;

			//Fade in the new cell.
			//this.slider.currentCell.className = 'higher';
			if ( this.options.effect == 'fade' ) {
				new Effect.Appear( this.slider.currentCell, { duration: this.options.transitionDuration } );
			} else if ( this.options.effect == 'slide' ) {
				// Animate the next cell in from off screen.
				if ( slideDirection == 'left' || slideDirection == 'right' ) {
					cellMoveX = 0;
					this.slider.currentCell.style.top = '0px';
					this.slider.currentCell.style.left = this.options.width+'px';
					if ( slideDirection == 'right' ) {
						this.slider.currentCell.style.left = (this.options.width*-1)+'px';
					}
					cellMoveY = 0;
				} else if ( slideDirection == 'up' || slideDirection == 'down' ) {
					cellMoveY = 0;
					this.slider.currentCell.style.top = this.options.height+'px';
					this.slider.currentCell.style.left = '0px';
					if ( slideDirection == 'down' ) {
						cellMoveY = 0;
						this.slider.currentCell.style.top = (this.options.height*-1)+'px';
					}
					cellMoveX = 0;
				}
				this.slider.currentCell.show();
				new Effect.Move( this.slider.currentCell, { x:cellMoveX, y:cellMoveY, mode:'absolute', duration:this.options.transitionDuration, transition:Effect.Transitions.sinoidal } );
			}

			//Rebuild the links to images.
			if (this.slider.rebuildLinks == true) {
				this.rebuildUI();
			}

			if (this.slider.playSlideshow == true) {
				clearTimeout(this.slider.timeout);
				this.slider.timeout = setTimeout( this.next.bind( this ), this.options.slideshowDuration );
			}

		},

		/**
		 * Goes to the next image.
		 */
		next: function()
		{
			if (this.slider.currentCellNumber == this.slider.cellCount) {
				goto = 1;
			} else {
				goto = this.slider.currentCellNumber + 1;
			}
			this.swapCell(goto);
		},

		/**
		 * Goes to the previous image.
		 */
		previous: function()
		{
			if (this.slider.currentCellNumber == 1) {
				goto = this.slider.cellCount;
			} else {
				goto = this.slider.currentCellNumber - 1;
			}
			this.swapCell(goto);
		},

		/**
		 * Goes to the first image.
		 */
		first: function()
		{	
			this.swapCell(1);
		},

		/**
		 * Goes to the last image.
		 */
		last: function()
		{	
			this.swapCell(this.slider.cellCount);
		},
			
		/**
		 * Toogle the slideshow between play and pause mode.
		 */
		togglePlayPause: function()
		{
			if (this.slider.playMode == 'play') {
				this.pauseSlideshow();
			} else if (this.slider.playMode == 'pause') {
				this.playSlideshow()
			}
		},
		
		/**
		 * Play the slideshow
		 */
		playSlideshow: function()
		{
			this.slider.playMode = 'play';
			this.next();
			this.slider.timeout = setTimeout( this.next.bind( this ), this.options.slideshowDuration );
			this.domElements.buttonPlay.update( '<span>pause</span>' );
			this.domElements.buttonPlay.className = 'ui-slider-button-'+this.slider.playMode;
		},

		/**
		 * Pause the slideshow
		 */
		pauseSlideshow: function()
		{	
			this.slider.playMode = 'pause';
			clearTimeout(this.slider.timeout);
			this.slider.currentCell.show();
			this.domElements.buttonPlay.update( '<span>play</span>' );
			this.domElements.buttonPlay.className = 'ui-slider-button-'+this.slider.playMode;
		},
		
		/**
		 * Rebuild the text and handers for the image links.
		 */
		rebuildUI: function()
		{
			startNum = this.slider.currentCellNumber - this.slider.linksPadding;
			endNum = startNum + this.slider.linksNumber;
			// Refine the start and end numbers.
			if (startNum < 1) {
				startNum = 1;
				endNum = startNum + this.slider.linksNumber;
			} else if (startNum + this.slider.linksNumber > this.slider.cellCount) {
				startNum = this.slider.cellCount - this.slider.linksNumber + 1;
				endNum = this.slider.cellCount;
			}
			// The 'fewer' cell.
			if (startNum > 1) {
				this.domElements.cellLinksFewer.update('...');
			} else {
				this.domElements.cellLinksFewer.update('');
			}
			// The 'more' cell.
			if (endNum < this.slider.cellCount) {
				this.domElements.cellLinksMore.update('...');
			} else {
				this.domElements.cellLinksMore.update('');
			}
			// Content and handlers for the links.
			var content = startNum;
			for (i = 1; i <= this.slider.linksNumber; i ++) {
				link = this.domElements['link_'+i];
				link.update(content);
				if (content == this.slider.currentCellNumber) {
					link.addClassName('current');
				} else {
					link.removeClassName('current');
				}
				// Kill the current handler for the link.
				link.stopObserving('click');
				if (content <= this.slider.cellCount) {
					link.observe('click', this.swapCell.bind(this, content));
					content ++;
					//bind;
				} else {
					content = '';
				}
			}
			//Update the image number text.
			this.domElements.cellCount.update( this.slider.currentCellNumber + ' of ' + this.slider.cellCount );
		}
		//End of last method definition.
		
	});
	
