var Photoset = Class.create({
	initialize: function(element, info, quicknav) {
		this.element = $(element);
		this.info = $(info);
		this.quicknav = $(quicknav);
		
		if (!this.element || !this.info) return;
		
		this.options = Object.extend({
			delay: 0.3,
			durations: {
				appear: 0.4,
				resize: 0.5,
				scroll: 1.4,
				buttonAppear: 0.2,
				buttonFade: 0.2,
				infoAppear: 0.28,
				infoFade: 0.6 // niet langer dan scroll
			},
			transition: function(pos) {
		      return ((pos/=0.5) < 1 ? 0.5 * Math.pow(pos, 4) :
		        -0.5 * ((pos-=2) * Math.pow(pos,3) - 2));
			},
			width: 500,
			photos: [],
			marginRight: 15,
			images: {
				loading: '/images/common/loading_big_grey.gif',
				blank:   '/images/common/blank.gif'
			}
		}, arguments[3] || {});
		
		this.photoElements = [];
		this.prepare();
	},
	
	prepare: function() {
		// make sure there are images
		this.photos = this.options.photos;
		if (this.photos.length == 0) return;
		
		// width
		this.element.down('.photos').setStyle({
			width: this.photos.length * this.options.width + this.photos.length * this.options.marginRight + 'px'
		});
		
		// CSS height
		this.options.height = this.element.getHeight();
		
		// hide quicknav
		//[this.info, this.quicknav].invoke('setStyle', { visibility: 'hidden' });
		
		// insert innerNavigation
		this.element.insert(this.innerNavigation = new Element('div', { className: 'innerNavigation' }
		)
			.insert(
					new Element('a', { href: '#', className: 'prev' }).hide()
						.insert(new Element('div', { className: 'button' }))
			)
			.insert(
					new Element('a', { href: '#', className: 'next' }).hide()
						.insert(new Element('div', { className: 'button' }))
			)
		);
		
		// preload the first image
		var preload = new Image();
		preload.onload = function() {
			preload.onload = Prototype.emptyFunction;
			
			// insert all the images
			this.photos.each(function(photo, i) {
				var imageDiv = new Element('div', {
					className: 'photo',					
					id: 'photo_' + photo.id
				}).setStyle({
					backgroundImage: 'url("' + this.options.images.loading + '")',
					width: this.options.width + 'px',
					height: preload.height + 'px',
					marginRight: this.options.marginRight + 'px'//,
					//left: ((i * this.options.marginRight) + this.options.width * i) + 'px'
				}).insert(new Element('img', {
					src: this.options.images.blank
				}).setStyle({
					width: this.options.width + 'px',
					height: preload.height + 'px'
				}).setOpacity(0));
				
				this.element.down('.photos').insert(imageDiv);
				
				this.photoElements.push(imageDiv);
			}.bind(this));
			
			
			var index = this.getPhotoIndex(this.options.startID || this.photos[0].id);
			// show first image
			this.preloadPhoto(index);
			
			/*var showThese = [this.info];
			if (this.photos.length != 1) {
				showThese.push(this.quicknav);
			}
			else {
				//this.quicknav.hide();
			}*/
			[this.info].invoke('setStyle', { visibility: 'visible' });
			
			// information
			this.setInfo(index);
			/*this.info.down('.overflow').setStyle({
				height: this.info.down('.info').getHeight() + 'px'
			});*/
			
			// position
			this.jumpTo(index);
			this.position = index;
			
			this.startObserving();
		}.bind(this);
		preload.src = this.getImageSrc(this.photos[0].image);
		
		// insert links
		/*this.photos.each(function(photo, i) {
			this.quicknav.insert(new Element('a', { rel: i }));
		}.bind(this));
		this.markQuicknav(0);*/
	},
	
	startObserving: function() {
		//this.quicknav.observe('click', this.delegateQuicknav.bindAsEventListener(this));
		
		this.innerNavigation.observe('mouseover', this.innerNavigationHover.bindAsEventListener(this))
			.observe('mouseout', this.innerNavigationOut.bindAsEventListener(this))
			.observe('click', this.innerNavigationClick.bindAsEventListener(this));
	},
	
	
	/*
	 * Next / Prev
	 */
	next: function() {
		var next = this.position+1;
		
		//this.markQuicknav(next);
		this.scrollTo(next);
	},
	
	prev: function() {
		var prev = this.position-1;
		
		//this.markQuicknav(prev);
		this.scrollTo(prev);
	},
	
	/*
	 * Inner navigation
	 */
	
	innerNavigationClick: function(event) {
		var element = event.findElement('a');
		if (element) {
			event.stop();
			// alleen sliden als er geen effects zijn
			if (Effect.Queue.effects.length == 0)
				this[element.className]();
		}
	},
	
	innerNavigationHover: function(event) {
		var element = event.findElement('a');
		if (element) element.down('.button').setStyle({ backgroundPosition: '0px -37px' });
	},
	
	innerNavigationOut: function(event) {
		var element = event.findElement('a');
		if (element) element.down('.button').setStyle({ backgroundPosition: '0px 0px' });
	},

	
	/*
	 * Quick navigation
	 */
	delegateQuicknav: function(event) {
		var element = event.findElement('a');
		if (element) {
			this.scrollTo(element.rel);
			this.markQuicknav(element.rel);
		}
	},
	
	markQuicknav: function(index) {
		var element = this.quicknav.down('a[rel="' + index + '"]');
		if (element) {
			element.addClassName('visited').addClassName('position');
			element.siblings().invoke('removeClassName' , 'position');
			
		}
	},
	
	/*
	 * Image src
	 */
	getImageSrc: function(src) {
		return this.options.phpThumbUrl + '?src=' + src + '&w=' + this.options.width + '&q=100';
	},
	
	jumpTo: function(index) {
		this.scrollTo(index, true);
	},
	
	getPhotoIndex: function(id) {
		var index = false;
		this.photos.each(function(p, i) {
			if (p.id == id) {
				index = i;
			}
		});
		return index;
	},
	
	jumpToID: function(id) {
		var index = false;
		
		if (index) {
			this.jumpTo(index);
		}
	},
	/*
	 * Scrolling
	 */
	scrollTo: function(index, instant) {
		if (index == this.position) return;
		
		if (index > this.photos.length - 1) index = this.photos.length - 1;
		if (index < 0) index = 0;
		
		var isLast = (index == (this.photos.length - 1)),
			next = this.innerNavigation.down('.next'),
			prev = this.innerNavigation.down('.prev');
		
		if (!isLast && !next.visible()) next.appear({ duration: this.options.durations.buttonAppear });
		if (index > 0 && !prev.visible()) prev.appear({ duration: this.options.durations.buttonAppear });
		
		
		// info effect
		var queue = Effect.Queues.get('info_' + this.info.identify());
		queue.each(function(effect) { effect.cancel(); });
		new Effect.Fade(this.info.down('.fade'), {
			queue: { position: 'end', scope: 'info_' + this.info.identify() },
			duration: instant ? 0.01 : this.options.durations.infoFade
		});
		
		// first
		if (index < 0) index = 0;
		
		// start loading it before scrolling
		this.preloadPhoto(index);
		
		if (this._scrollEffect) this._scrollEffect.cancel();
		this._scrollEffect = new Effect.Morph(this.element.down('.photos'), {
			style: {
				left: '-' + ((index * this.options.marginRight) + this.options.width * index) + 'px'
			},
			afterFinish: function() {
				// load the image when you get there
				this.preloadPhoto(index);
				
				// preload surrounding
				this.preloadSurrounding(index);
				
				// update info
				this.setInfo(index);
				var queue = Effect.Queues.get('info_' + this.info.identify());
				queue.each(function(effect) { effect.cancel(); });
				
				var infoHeight = this.info.down('.info').getHeight();
				if (this.info.down('.overflow').getHeight() != infoHeight) {
					new Effect.Morph(this.info.down('.overflow'), {
						style: {
							height: infoHeight + 'px'
						},
						queue: { position: 'end', scope: 'info_' + this.info.identify() },
						duration: instant ? 0.01 : 0.1
					});
				}
				
				new Effect.Appear(this.info.down('.fade'), {
					queue: { position: 'end', scope: 'info_' + this.info.identify() },
					duration: instant ? 0.01 : this.options.durations.infoAppear
				});
				
				
				// update position
				this.position = parseInt(index);
				
				// next prev
				if (index == 0) prev.fade({ duration: this.options.durations.buttonFade });
				if (isLast) next.fade({ duration: this.options.durations.buttonFade });
			}.bind(this),
			duration: instant ? 0.01 : this.options.durations.scroll,
			transition: this.options.transition
		});
	},
	
	
	/*
	 * Information
	 */
	setInfo: function(index) {
		var photo = this.photos[parseInt(index)];
		
		if (photo.description) {
			this.info.down('.info').show().update(photo.description);
			//this.info.down('h1').show();
			
			this.info.down('.number').update((parseInt(index) + 1) + '/' + this.photos.length);
		}
		else {
			this.info.down('.info').hide().update();
			//this.info.down('h1').hide();
			
			this.info.down('.number').update((parseInt(index) + 1) + '/' + this.photos.length);	
		}
	},
	
	preloadSurrounding: function(index) {
		var prev = index == 0 ? this.photos.length-1 : index - 1,
			next = index == this.photos.length-1 ? 0 : index + 1;
		
		//console.log(next);
		this.preloadPhoto(prev);
		this.preloadPhoto(next);		
	},
	
	/*
	 * Preloading / Showing
	 */
	preloadPhoto: function(index) {
		var photo = this.photos[index];
		
		if (photo._preloaded || photo._preloading) return;
		photo._preloading = true;
		
		var photoElement = this.photoElements[index],
			img = photoElement.down('img'),
			src = this.getImageSrc(photo.image);
		
		// preload src
		var preload = new Image();
		preload.onload = function() {
			preload.onload = Prototype.emptyFunction;
			
			// dimensies instellen
			img.setStyle({
				width: preload.width + 'px',
				height: preload.height + 'px'
			});
			
			// eventueel element groter maken
			if (preload.height > this.element.getHeight() && preload.height != this.options.height) {
				this.options.height = preload.height;
				
				if (this._resizeEffect) this._resizeEffect.cancel();
				this._resizeEffect = new Effect.Morph(this.element, {
					style: {
						height: preload.height + 'px'
					},
					afterFinish: function() {
						this.photoElements.each(function(p) {
							[p].invoke('setStyle', {
								height: preload.height + 'px'
							});
						});
					}.bind(this)
				});
			}
			
			// afbeelding source
			img.src = src;
			
			// infaden
			new Effect.Morph(photoElement, {
				queue: { position: 'end', scope: 'appear_' + photoElement.identify() },
				duration: this.options.durations.resize,
				style: {
	         		width: preload.width + 'px',
	         		height: preload.height + 'px'
	         	}
	        });
	        new Effect.Appear(img, {
	        	queue: { position: 'end', scope: 'appear_' + photoElement.identify() },
	        	duration: this.options.durations.appear,
				afterFinish: function() {
					// preloaded
					photo._preloaded = true;
					photo._preloading = false;
					photoElement.setStyle({ 
						backgroundColor: '#fff',
						backgroundImage: 'none'
					});
					
					// preload surrounding
				}.bind(this)
	        });
		}.bind(this);
		preload.src = src;
	}
});
