// Mootools 1.2 based lightbox slideshow with gradient background
// (c)2010 Standupweb

// class loosely based on http://davidwalsh.name/slideshow-preload-images
var dwSlideshow = new Class({
    Implements: Options,
    options: {
		// I actually use a JSON service to retrieve the images
		images : ['image1big.jpg','image2big.jpg','image3big.jpg', 'image4big.jpg'],
		slideshowHolderId : 'slideshow-holder',
		progressId : 'progress',
		interval: 10000,
		margin: 100 // margin around the picture in the slideshow
    },
	// index of the current picture
	index: 0,
	// array containing the img elements
	slides: new Array(),
	// element containing the lightbox + the image
	holder: 0,
	// if the slideshow starts before the image is loaded, we need to use a flag
	wantToStart: false,
	canStart:false,
	// timer id for the delay
	timer:0,
	// stores the number of images
	imagesArrayLength:0,
	updateProgress : function(num) {
		this.progress.set('text',this.progressTemplate.replace('{x}',num));
	},
    initialize: function(options){
		// 1/ misc init
		this.setOptions(options);
		this.holder = $(this.options.slideshowHolderId); 
		this.imagesArrayLength=this.options.images.length;
		this.progressTemplate = 'Loading image {x} of ' + this.options.images.length;
		this.progress = $(this.options.progressId);
		this.updateProgress('text','0');
		
		// 2/ load images
		var loader = new Asset.images(this.options.images, {
			onProgress: function(c,index) {
				this.updateProgress('text',index + 1);
			}.bind(this),
			onComplete: function() {
				/* put images into page */
				this.options.images.each(function(im) {
					var image = new Element('img',{src:im, styles: { opacity:0, top:0, left:0, position:'absolute', 'z-index': 10 } }).inject(this.holder);
					// IE does not know the naturalWidth/naturalHeight attributes, so we need to set it explicitly
					// since we use it later for resizing
					// I put it in title since w3c saysabout title: "Specifies extra information about an element"
					image.set('title', image.width+'x'+image.height);
					this.slides.push(image);
					this.holder.setStyle('background','url(../images/logo.png) center 80px no-repeat');
				}, this);
				this.progress.set('text','');
				this.canStart=true;
				if (this.wantToStart) { this.startAtIndex(0); }
			}.bind(this)
		});
	},
	// start the slideshow with the picture at index = index in the slides array
	startAtIndex: function(index){
		if (!this.canStart) {
			this.wantToStart = true;
			this.index=index;
		}
		else {
			if (this.wantToStart) {
				this.wantToStart=false;
			} else {
				this.index=index;
			}
			this.update();
			this.initArrows();
			for (i=0; i<this.imagesArrayLength; i++) {
				if (i == this.index) {
					this.slides[this.index].tween('opacity', 1);
					this.relocateArrows();
				}
				else 
					this.slides[i].setStyle('opacity', '0');
			}			
			this.start();
		}
	},
	// initiates and delays the display of the next picture
	start: function () {
		this.timer = this.next.delay(this.options.interval, this);
	},
	// display the next picture in the slides array
	next: function() {
		$clear(this.timer);
		this.holder.setStyle('background','');
		this.slides[this.index].fade(0);
		++this.index;
		this.index = (this.slides[this.index] ? this.index : 0);
		this.slides[this.index].fade(1);
		this.relocateArrows();
		this.timer = this.next.delay(this.options.interval, this);
	},
	// display the previous picture in the slides array
	previous: function() {
		$clear(this.timer);
		this.holder.setStyle('background','');
		this.slides[this.index].fade(0);
		--this.index;
		this.index = (this.index>=0 ? this.index : (this.slides.length-1));
		this.slides[this.index].fade(1);
		this.relocateArrows();
		this.timer = this.next.delay(this.options.interval, this);
	},
	// update location and size of lightbox and picture (on start or window resize)
	update: function() {
		var bodyElement = $(document.body);
		// get center coordinate of the window
		var viewPortCenterX = bodyElement.getSize().x/2;
		var viewPortCenterY = bodyElement.getSize().y/2;
		for (i=0; i<this.imagesArrayLength; i++) {
			// retrieve current picture
			var slide = this.slides[i];
			// retrieve real dimension of the pictures
			// not that without IE, slide.naturalHight would have been enough...
			var naturalDimensions = slide.get('title').split('x');
			var width = naturalDimensions[0];
			var height = naturalDimensions[1];
			// compute picture width and height depending on its size and the size of the window
			if ((width*viewPortCenterY)>(height*viewPortCenterX)) {
				var reducedWidth=bodyElement.getSize().x-this.options.margin;
				if (reducedWidth>width) reducedWidth=width;
				var reducedHeight=parseInt(height*reducedWidth/width);
			} else {
				var reducedHeight=bodyElement.getSize().y-this.options.margin;
				if (reducedHeight>height) reducedHeight=height;
				var reducedWidth=parseInt(width*reducedHeight/height);
			}
			// apply position and dimension to the current picture
			slide.set('height', reducedHeight);
			slide.set('width', reducedWidth);
			slide.setStyles({top: -(reducedHeight/2).toInt(), left: -(reducedWidth/2).toInt()});
			// relocate the arrows
			this.relocateArrows();
		}
	},
	relocateArrows: function(){
		var bodyElement = $(document.body);
		// get center coordinate of the window
		var viewPortCenterX = bodyElement.getSize().x/2;
		var viewPortCenterY = bodyElement.getSize().y/2;
		var slide = this.slides[this.index];
		var reducedWidth = slide.get('width');
		$('left-arrow').morph({top:(viewPortCenterY-25).toInt(), left:(viewPortCenterX-60-(reducedWidth/2)).toInt()});
		$('right-arrow').morph({top:(viewPortCenterY-25).toInt(), left:(viewPortCenterX+10+(reducedWidth/2)).toInt()});
	},
	initArrows: function(){
		var bodyElement = $(document.body);
		// get center coordinate of the window
		var viewPortCenterX = bodyElement.getSize().x/2;
		var viewPortCenterY = bodyElement.getSize().y/2;
		$('left-arrow').setStyles({top:viewPortCenterY, left:viewPortCenterX-60});
		$('right-arrow').setStyles({top:viewPortCenterY, left:viewPortCenterX+10});
	}
});

// main class
var SwGradientLightbox = new Class({
    Implements: [Options, Events],
    options: {
		className: 'swGradientLightbox',		// all pictures in the page that want to appear in the slideshow should have this class
		bigImagePostfix: '-big',				// ex: if the thumbnail is 'image.jpg' the slideshow will display 'image-big.jpg'  
		gradientBgId: 'gradient-bg', 			// id of the lightbox
		onStart: Class.empty
    },
	slideshow: 0,
    initialize: function(options){
		this.setOptions(options);
		var index =-1;
		// stores the image sources name
		var images= new Array();
		// insert the html for the slideshow
		var gradientBg = new Element('div', {'id':this.options.gradientBgId});
		gradientBg.set('html', '<div id="grad-top-left"></div><div id="grad-top-right"></div><div id="grad-bottom-left"></div><div id="grad-bottom-right"></div><div id="left-arrow"></div><div id="right-arrow"></div><div id="slideshow-holder"><div id="progress"></div></div>');
		$(document.body).grab(gradientBg, 'top');
		// hide the lightbox
		gradientBg.setStyles({'opacity':0, 'z-index':-100});
		// add click events to start the slideshow
		$$('.'+this.options.className).each (function (imgItem, i){
			var src = imgItem.get('src');
			images[i] = src.substring(0, src.length-4) + this.options.bigImagePostfix + src.substring(src.length-4, src.length);
			imgItem.addEvent('click', function(i){
				index=i;
				$(document.body).setStyle('overflow', 'hidden');
				this.show(i);
			}.bind(this, i));
		}, this);
		// init the slideshow
		this.slideshow = new dwSlideshow({slideshowHolderId : 'slideshow-holder', images: images});
		// add click events to control/stop  the slideshow
		$('slideshow-holder').addEvent('click', function(){
			gradientBg.setStyles({'opacity':0, 'z-index':-100});
			$(document.body).setStyle('overflow', 'auto');
			index=-1;
		}.bind(this));
		$('grad-bottom-left').addEvent('click', function(){
			if (index>=0) this.slideshow.previous();
		}.bind(this));
		$('grad-top-left').addEvent('click', function(){
			if (index>=0) this.slideshow.previous();
		}.bind(this));
		$('left-arrow').addEvent('click', function(){
			if (index>=0) this.slideshow.previous();
		}.bind(this));
		$('grad-bottom-right').addEvent('click', function(){
			if (index>=0) this.slideshow.next();
		}.bind(this));
		$('grad-top-right').addEvent('click', function(){
			if (index>=0) this.slideshow.next();
		}.bind(this));
		$('right-arrow').addEvent('click', function(){
			if (index>=0) this.slideshow.next();
		}.bind(this));
		window.addEvent('keydown', function(e){
			e.stop();
			if (e.key=='left') {
				this.slideshow.previous();
			} else if (e.key=='right') {
				this.slideshow.next();
			} else if (e.key=='esc') {
				gradientBg.setStyles({'opacity':0, 'z-index':-100});
				$(document.body).setStyle('overflow', 'auto');
				index=-1;
			}
		}.bind(this));
		// add the window resize event
		window.addEvent('resize', function(){if (index>=0) this.paint(index);}.bind(this));
	},
	initGradDiv: function(){
		// compute size of the light box made of 4 div in order to display a nicer gradient
		var bodyElement = $(document.body);
		var viewPortWidth = bodyElement.getSize().x;
		var viewPortHeight = bodyElement.getSize().y;
		var viewPortOriginX = bodyElement.getScroll().x;
		var viewPortOriginY = bodyElement.getScroll().y;
		var midX = parseInt(viewPortWidth/2); 
		var midY = parseInt(viewPortHeight/2); 
		$(this.options.gradientBgId).setStyles({ 'width':viewPortWidth+'px', 'height':viewPortHeight+'px','top':viewPortOriginY+'px','left':viewPortOriginX+'px' });
		// init the 4 divs surrounding the pictures
		$('grad-bottom-left').setStyles({'top':midY+'px', 'left':'0px', 'width':midX+'px', 'height':midY+'px'});
		$('grad-bottom-right').setStyles({'top':midY+'px', 'left':midX+'px', 'width':midX+'px', 'height':midY+'px'});
		$('grad-top-left').setStyles({'top':'0px', 'left':'0px', 'width':midX+'px', 'height':midY+'px'});
		$('grad-top-right').setStyles({'top':'0px', 'left':midX+'px', 'width':midX+'px', 'height':midY+'px'});
	},
	resize: function(i, update) {
		var bodyElement = $(document.body);
		// get center coordinate of the window
		var viewPortCenterX = bodyElement.getSize().x/2;
		var viewPortCenterY = bodyElement.getSize().y/2;
		this.initGradDiv();
		$('slideshow-holder').setStyles({
			'top':viewPortCenterY +'px',
			'left':viewPortCenterX +'px'
		});
		if (update) {
			this.slideshow.update();
		} else {
			$(this.options.gradientBgId).setStyles({ 'opacity': 1, 'z-index': 100 });
			this.slideshow.startAtIndex(i);
			this.fireEvent('start', this);
		}
	},
	show: function(i) {
		this.resize(i, false);
	},
	paint: function(i) {
		this.resize(i, true);
	}
});

