Gallery = new JS.Class('Gallery', {
	include: JS.State,
	
	initialize: function(items, options) {
		items = Ojay(items);
		
		this._current  = 0;
		this._images   = [];
		this._titles   = [];
		this._captions = [];
		
		this._options = options || {};
		this._options.width  = this._options.width  || 900;
		this._options.height = this._options.height || 750;
		
		this._thumbnails = items.map(function(item, i) {
			var thumb   = item.children(this.klass.THUMBNAIL_SELECTOR).at(0),
				title   = item.children(this.klass.TITLE_SELECTOR).node.innerHTML,
				caption = item.children(this.klass.CAPTION_SELECTOR).node.innerHTML;
			
			var image = Ojay(Ojay.HTML.img({
				src: thumb.node.href,
				alt: thumb.children('img').node.alt
			})).setStyle({
				position: 'absolute',
				top:      0,
				left:     0,
				zIndex:   1,
				opacity:  0
			}).hide();
			
			this._images[i]   = image;
			this._titles[i]   = title;
			this._captions[i] = caption;
			
			if (i === this._current) {
				image.setStyle({
					zIndex:  3,
					opacity: 1
				}).show();
			}
			
			thumb.on('click', function(el, evnt) {
				evnt.stopDefault();
				
				if (!this._overlay) this._makeOverlay();
				
				this.setImage(i, false).open(i);
			}, this);
		}, this);
		
		this.setState('READY');
	},
	
	_makeOverlay: function() {
		if (this._overlay) return;
		
		this._overlay  = new Ojay.ContentOverlay().center();
		this._pageMask = new Ojay.PageMask({
			color: '#ffffff',
			opacity: 0.8
		}).positionBehind(this._overlay);
		
		this._imageContainer = Ojay(Ojay.HTML.div({className: 'images'})).setStyle({
			position: 'relative',
			overflow: 'hidden',
			width:    this._options.width  + 'px',
			height:   this._options.height + 'px'
		}, this);
		
		this._overlay.insert(this._imageContainer);
		
		this._closeButton = Ojay(Ojay.HTML.span({className: 'close'}, 'Close'));
		this._counter     = Ojay(Ojay.HTML.span({className: 'counter'}));
		
		this._closeButton.on('click')._(this).close();
		
		this.updateCounters(0);
		this._overlay.insert(this._closeButton).insert(this._counter);
		
		if (this._images.length > 1) {
			this._prevButton = Ojay(Ojay.HTML.div({className: 'previous'}, 'Previous'));
			this._nextButton = Ojay(Ojay.HTML.div({className: 'next'}, 'Next'));
			
			this._prevButton.on('click')._(this).previousImage();
			this._nextButton.on('click')._(this).nextImage();
			
			this._overlay.insert(this._prevButton).insert(this._nextButton);
		}
		
		this._images.forEach(function(image) {
			this._imageContainer.insert(image);
		}, this);
		
		this._titleElement   = Ojay(Ojay.HTML.p({className: 'image-title'}));
		this._captionElement = Ojay(Ojay.HTML.div({className: 'gallery-image-caption'}));
		
		this._imageContainer.insert(this._captionElement, 'after');
		this._imageContainer.insert(this._titleElement, 'after');
		
		this.setImage(0, false);
	},
	
	nextImage: function() {
		var index = this._current + 1;
		if (index >= this._thumbnails.length) index = 0;
		this.setImage(index);
	},
	
	previousImage: function() {
		var index = this._current - 1;
		if (index < 0) index = this._thumbnails.length - 1;
		this.setImage(index);
	},
	
	setImage: function(index, animate) {
		if (this.inState('TRANSITIONING') ||
			(index === this._current && !this.inState('READY')) ||
			index < 0 ||
			index >= this._thumbnails.length) return this;
		
		if (this._overlay) {
			this.updateCounters(index);
			this._titleElement.setContent(this._titles[index]);
			this._captionElement.setContent(this._captions[index]);
		}
		
		var currentImage = this._images[this._current],
			nextImage    = this._images[index];
		
		if (index === this._current) {
			currentImage.setStyle({zIndex: 3, opacity: 1}).show();
			return this;
		}
		
		if (animate === false) {
			currentImage.hide().setStyle({zIndex: 1, opacity: 0})
			._(nextImage).setStyle({zIndex: 3, opacity: 1}).show();
		} else {
			this.setState('TRANSITIONING');
			currentImage.setStyle({zIndex: 1})
			._(nextImage).setStyle({zIndex: 3}).show().animate({
				opacity: {
					to: 1
				}
			})
			._(currentImage).hide().setStyle({opacity: 0})
			._(this).setState('OVERLAID');
		}
		
		this._current = index;
		
		return this;
	},
	
	updateCounters: function(index) {
		this._counter.setContent((index + 1) + '-' + this._thumbnails.length);
	},
	
	states: {
		READY: {
			open: function() {
				if (!this._overlay) this._makeOverlay();
				
				this._pageMask.show('fade')
				._(this._overlay).fitToContent().center().show('zoom')
				._(this).setState('OVERLAID');
				
				return this;
			}
		},
		
		OVERLAID: {
			close: function() {
				this._overlay.hide('zoom')
				._(this._pageMask).hide('fade')
				._(this).setState('READY');
				
				return this;
			}
		},
		
		TRANSITIONING: {}
	},
	
	extend: {
		THUMBNAIL_SELECTOR: 'a.thumbnail',
		TITLE_SELECTOR:     '.image-title',
		CAPTION_SELECTOR:   '.image-caption'
	}
});

