/**
 * Class for loading and displaying a gallery using XHR.
 * @author Jeff Fohl
 * @copyright Godengo Inc., 2009
 *
 * DEPENDENCIES:
 *  prototype.js and effects.js must be loaded prior to this
 **/

var SlideshowGallery = Class.create();

SlideshowGallery.prototype = {

initialize: function(galleryContainer, options) {
	        // parameters. these are the default values.
			this.options = Object.extend({
				increment : 2, // seconds between fades
				fadeSpeed : 0.5, // duration of fade in seconds
				imageHeight : 258, // image height
				imageWidth : 512, // image width
				z: 9999, // the zIndex of the scrim and spinner
				controls : false, // specifies whether or not to show play/pause controls
				spinnerURL : "/core/media/images/ajax-loader.gif", // url to the loading image
				scrimColor : "#ffffff", // color of the scrim
				scrimOpacity : 0, // opacity of the scrim
				menu : "none", // type of menu: text, number, or none
				descriptions : false, // show photo descriptions?
				photoCredits : false, // show photo credits?
				captions : false, // show the captions for each slide?
				crop : false, // true: zoom-crop enabled. false: images will be stretched to fit the dimensions supplied
				quality : 85,
				title : false, // show the title of the gallery?
				mediaPath : "/" // the path to media on the server. This should be supplied by Rivista automatically.
				 }, options || {});
			this.backendurl = '/core/ajaxserver.php'; // where we get our data
			this.galleryContainer = $(galleryContainer); // the element that contains the entire gallery in the markup
			this.parentContainer = this.galleryContainer.up();
			this.galleryid = this.galleryContainer.id.replace(/gallery_/i,''); // the gallery id
			this.images = []; // the image in slideshow.
			this.options.mediaPath = this.options.mediaPath+"/";
			this.options.mediaPath.replace("//","/");
			this.imageContainers = []; // the divs that contain the images.
			this.imageLinks = []; // the URLs to which the photos will link.
			if (this.options.crop === true) {
				this.zc = 1;
				this.iar = 0;
			}
			else {
				this.zc = 0;
				this.iar = 1;
			}
			
			if (this.options.descriptions === true || this.options.photoCredits === true || this.options.captions === true) {
				this.contentContainers = [];
			}
			if (this.options.title === true) {
				this.title = new Element('h2').addClassName('galleryTitle');
			}
			this.gallerydata = null; // the container of the JSON data
			this.counter = 0; // a counter that helps us figure out when all the images have finished loading
			this.currentSlide = 0; // the slide that is now visible
			this.nextSlide = 1; // the next slide to be shown
			this.slideIncrement = null; // holds the setTimeout for the next slide
			this.scrim = null; // an opaque layer over the slide show while the images are loading, to prevent interaction
			this.playSpeed = (this.options.fadeSpeed+this.options.increment)*1000; // actual time before next fade
			this.dimensions = this.galleryContainer.getDimensions(); // the dimensions of the entire gallery area
			this.spinner = new Element('img' , {style : 'position:absolute; z-index:'+(this.options.z)+5});
			this.spinner.onload = function() {
				var top = Math.round((this.options.imageHeight/2)-(this.spinner.height/2));
				var left = Math.round((this.options.imageWidth/2)-(this.spinner.width/2));
				this.spinner.style.top = top+"px";
				this.spinner.style.left = left+"px";
				this.galleryContainer.insert({top:this.spinner});
			}.bind(this);
			this.spinner.src = this.options.spinnerURL;
			this.play = true; // play or stop
			if (this.options.menu == "text" || this.options.menu == "number") {
				this.menu = new Element('div').addClassName('galleryMenu'); // the menu
				this.menu.style.zIndex = (this.options.z)+2;
				this.galleryContainer.insert({bottom : this.menu});
				this.menuItems = []; // the <a> elements in the menu
				this.menuItemContainers = []; // the elements that contain the <a> elements in the menu
			}
			if (this.options.controls === true) {
				this.controls = new Element('div').addClassName('controls');
				this.previousButton = new Element('a' , {href : '#'}).addClassName('previous').update('&laquo;');
				this.controls.style.zIndex = (this.options.z)+3;
				this.nextButton = new Element('a' , {href : '#'}).addClassName('next').update('&raquo;');
				this.playPauseButton = new Element('a' , {href : '#'}).addClassName('play').update('Pause');
				this.previousButton.onclick = function() {
					this.showPreviousSlide();
					return false;
				}.bind(this);
				this.playPauseButton.onclick = function() {
					this.playPause();
					return false;
				}.bind(this);
				this.nextButton.onclick = function() {
					this.showNextSlide();
					return false;
				}.bind(this);
				this.controls.insert({bottom:this.previousButton});
				this.controls.insert({bottom:this.playPauseButton});
				this.controls.insert({bottom:this.nextButton});
				this.galleryContainer.insert({bottom:this.controls});
			}
			if (this.options.descriptions === true) {
				this.descriptions = [];
			}
			if (this.options.photoCredits === true) {
				this.photoCredits = [];
			}
			if (this.options.captions === true) {
				this.captions = [];
				this.captionLinks = [];
			}
			this.get();
		},
		
		//retrieve gallery information and send back as JSON object
		get: function() {
			var ajax = new Ajax.Request('/core/ajaxserver.php', {
				method: 'get',
				parameters: {'req':'getGallery', 'galleryid': this.galleryid },
				asynchronous: true,
				onComplete: function(transport) {
					var thisGallery = this;
					var menuClick = function() {
								window.clearTimeout(thisGallery.slideIncrement);
								thisGallery.nextSlide = this.position;
								thisGallery.play = false;
									if (thisGallery.options.controls === true) {
										thisGallery.playPauseButton.update('Play');
									}
								thisGallery.xFade();
								return false;
								};
					this.gallerydata = transport.responseText.evalJSON(true);
					this.galleryImages = this.gallerydata.items;
					if (this.title) {
						this.title.update(this.gallerydata.title);
						this.parentContainer.insert({top:this.title});
					}
					this.scrim = new Element('div' , {style : 'position:absolute; z-index:'+((this.options.z)+4)+'; width:'+this.dimensions.width+'px; height:'+this.dimensions.height+'px; background-color:'+this.options.scrimColor+';'});
					this.scrim.addClassName('scrim').setOpacity(this.options.scrimOpacity);
					this.galleryContainer.insert({top:this.scrim});
					for(var i=0;i<this.galleryImages.length;i++) {
						this.imageContainers[i] = new Element('div' , {
								id: 'gallerycontent'+this.galleryid+'_'+this.galleryImages[i].id,
								style : "z-index:"+((this.options.z) - i)+"; position:absolute;" }).addClassName('imageContainer').setOpacity(0);
						this.images[i] = new Image([this.options.imageWidth],[this.options.imageHeight]);
						if (this.options.menu == "text" || this.options.menu == "number") {
							this.menuItemContainers[i] = new Element('div', {style : 'display:none;'});
							this.menuItems[i] = new Element('a', {href:''});
							this.menuItems[i].position = i;
							switch (this.options.menu) {
							case "text" :
								this.menuItems[i].update(this.galleryImages[i].title);
								break;
							case "number" :
								this.menuItems[i].update(i+1);
								break;
							default :
								throw('Something is wrong!');
							}
							this.menuItems[i].onclick = menuClick;
							this.menuItemContainers[i].insert({bottom:this.menuItems[i]});
							this.menu.insert({bottom:this.menuItemContainers[i]});
						}
						this.imageLinks[i] = new Element ('a', {href : this.galleryImages[i].linkurl});
						this.imageLinks[i].insert({bottom:this.images[i]});
						this.imageContainers[i].insert({bottom:this.imageLinks[i]});
						this.galleryContainer.insert({bottom:this.imageContainers[i]});
						if (this.contentContainers) {
							this.contentContainers[i] = new Element ('div', { style : "z-index:"+((this.options.z) - (i+2))+"; position:absolute;" }).addClassName('contentContainer').setOpacity(0);						
							this.galleryContainer.insert({bottom : this.contentContainers[i]});
						}
						if (this.options.captions === true) {
							this.captions[i] = new Element ('div').addClassName('caption');
							this.captionLinks[i] = new Element ('a', {href : this.galleryImages[i].linkurl});
							this.captionLinks[i].update(this.galleryImages[i].title);
							this.captions[i].insert({bottom:this.captionLinks[i]});
							this.contentContainers[i].insert({bottom : this.captions[i]});
						}
						if (this.options.photoCredits === true) {
							this.photoCredits[i] = new Element ('div').addClassName('photo-credit');
							this.photoCredits[i].update(this.galleryImages[i].photocredits);
							this.contentContainers[i].insert({bottom : this.photoCredits[i]});
						}
						if (this.options.descriptions === true) {
							this.descriptions[i] = new Element ('div').addClassName('description');
							this.descriptions[i].update(this.galleryImages[i].description);
							this.contentContainers[i].insert({bottom : this.descriptions[i]});
						}
					}
					this.loadImages();
				}.bind(this)
			});
		},
		// we need to load the images separately, because the image data is not included in the JSON data.
		// we also need to handle the timing of the loading of the image data
		loadImages : function() {
			this.images[this.counter].onload = function() {
				if (this.options.menu == "text" || this.options.menu == "number") {
					this.menuItemContainers[this.counter].style.display = "block";
					// reset the scrim height in case the expanding menu bleeds over the edge
					this.scrim.style.height = (this.galleryContainer.getHeight())+"px";
				}
				if (this.counter === 0) {
					var b = new Effect.Opacity(this.imageContainers[0], { duration: this.options.fadeSpeed, from: 0, to: 1});
						if (this.contentContainers) {
						var c = new Effect.Opacity(this.contentContainers[0], { duration: this.options.fadeSpeed, from: 0, to: 1 });
					}
				}
				if (this.counter == (this.gallerydata.items.length)-1) {
								this.spinner.style.display = "none";
								if (this.options.menu == "text" || this.options.menu == "number") {
									this.menuItems[0].className = "selected";
									this.menuItems[0].parentNode.className = "selected";
								}
								var a = new Effect.Fade(this.scrim, { duration: this.options.fadeSpeed, from: this.options.scrimOpacity, to: 0 });
								this.slideIncrement = window.setTimeout(function(){this.xFade();}.bind(this), this.playSpeed);
							}
				else {
				this.counter++;
				this.loadImages(this.images[this.counter]);
				}
			}.bind(this);
			this.images[this.counter].src = '/core/includes/phpThumb/phpThumb.php?src='+this.options.mediaPath+'galleries/'+this.galleryid+'/'+this.galleryImages[this.counter].image+'&w='+this.options.imageWidth+'&h='+this.options.imageHeight+'&q='+this.options.quality+'&aoe=1&iar='+this.iar+'&zc='+this.zc;
		},
		
		// cross fade function
		xFade : function() {
			this.switchZ();
			var e = new Effect.Opacity(this.imageContainers[this.currentSlide], { duration: this.options.fadeSpeed, from: 1, to: 0 });
			var f = new Effect.Opacity(this.imageContainers[this.nextSlide], { duration: this.options.fadeSpeed, from: 0, to: 1 });
			if (this.contentContainers) {
				var g = new Effect.Opacity(this.contentContainers[this.currentSlide], { duration: this.options.fadeSpeed, from: 1, to: 0 });
				var h = new Effect.Opacity(this.contentContainers[this.nextSlide], { duration: this.options.fadeSpeed, from: 0, to: 1});
			}
			if (this.options.menu == "text" || this.options.menu == "number") {
				this.menuItems[this.currentSlide].className = "";
				this.menuItems[this.currentSlide].parentNode.className = "";
				this.menuItems[this.nextSlide].className = "selected";
				this.menuItems[this.nextSlide].parentNode.className = "selected";
			}
			this.currentSlide = this.nextSlide;
			this.nextSlide++;
			if (this.nextSlide == this.imageContainers.length) {
				this.nextSlide = 0;
				}
			if (this.play === true) {
				this.slideIncrement = window.setTimeout( function(){this.xFade();}.bind(this), this.playSpeed);
				}
			},
			
		showPreviousSlide : function() {
			window.clearTimeout(this.slideIncrement);
			this.play = false;
			if (this.options.controls === true) {
				this.playPauseButton.update("Play");
			}
			this.nextSlide = (this.currentSlide) - 1;
			if (this.nextSlide < 0) {
				this.nextSlide = (this.imageContainers.length)-1;
			}
			this.xFade();
		},
		
		showNextSlide : function() {
			window.clearTimeout(this.slideIncrement);
			this.play = false;
			if (this.options.controls === true) {
				this.playPauseButton.update("Play");
			}
			this.nextSlide = (this.currentSlide) + 1;
			if (this.nextSlide >= this.imageContainers.length) {
				this.nextSlide = 0;
			}
			this.xFade();
		},
		
		switchZ : function() {
			this.imageContainers[this.currentSlide].style.zIndex = (this.options.z)-1;
			this.imageContainers[this.nextSlide].style.zIndex = this.options.z;
			if (this.contentContainers) {
				this.contentContainers[this.currentSlide].style.zIndex = (this.options.z)-1;
				this.contentContainers[this.nextSlide].style.zIndex = this.options.z;
			}
		},
		
		playPause : function() {
			if (this.play === true) {
				window.clearTimeout(this.slideIncrement);
				this.play = false;
				if (this.options.controls === true) {
					this.playPauseButton.update("Play");
				}
			}
			else {
				window.clearTimeout(this.slideIncrement);
				this.play = true;
				if (this.options.controls === true) {
					this.playPauseButton.update("Pause");
				}
				this.xFade();
			}
		}
	};