var mooView = new Class({
	Binds: ['keyboardListener', 'mouseListener'],

	Implements: [Options, Events],

	options: {
		'rel': 'mooView',
		'allowSingleImage': false,
		'minWidth': 320,
		'minHeight': 240,
		'top': 40,
		'useKeyboard': true,
		'useMousewheel': true,
		'loopImages': false
	},

	initialize: function(options) {
		this.setOptions(options);

		// images groups
		this.images = [];

		// grab links
		this.links = $$('a[rel^=' + this.options.rel + ']');
		this.links.each(function(link) {
			link.removeEvents('click').addEvent('click', function(event) {
				event.stop();
			    this.click.apply(this, [link]);
			}.bind(this));
			link.removeEvents('mouseover').addEvent('mouseover', function() {
				link.store('title', link.title).removeProperty('title');
			});
			link.removeEvents('mouseout').addEvent('mouseout', function() {
				link.setProperty('title', link.retrieve('title'));
			});

			// create group
			if(this.images[link.rel] == null) {
				this.images[link.rel] = [];
			}

			// push link in group
			var dual = link.title.split('::');
			if(dual.length > 1) {
				this.images[link.rel].push(new Array(link, dual[0]));
			}
			else {
				this.images[link.rel].push(new Array(link, link.title));
			}
		}, this);
	},

	keyboardListener: function(event) {
		event = new Event(event);
		switch (event.key){
			case 'esc': this.close(); break;
			case 'left': this.prev(); break;
			case 'right': this.next(); break;
		}
	},

	mouseListener: function(event) {
		event = new Event(event);
		event.stop();
		if(event.wheel > 0) {
			this.prev();
		}
		else if(event.wheel < 0) {
			this.next();
		}
	},

	click: function(link) {
    	if($('mooViewOverlay') != null) {
    		return false;
		}

		// ie6 selects
		if(Browser.ie6) {
			$$('select').each(function(el) {
				el.style.visibility = 'hidden';
			});
		}

		// flash
		$$('object, embed').each(function(el) {
			el.style.visibility = 'hidden';
		});

		// events
		if(this.options.useKeyboard) {
			window.addEvent('keydown', this.keyboardListener);
		}
		if(this.options.useMousewheel) {
			window.addEvent('mousewheel', this.mouseListener);
		}

		// create elements
		this.overlay = new Element('div', {
			'id': 'mooViewOverlay'
		}).inject(document.body, 'top').setStyle('height', document.getScrollSize().y).set('opacity', 0.5).addEvent('click', this.close.bind(this));

		this.center = new Element('div', {
			'id': 'mooViewCenter',
			'class': 'mooViewLoading',
			'styles': {
				'margin-left': -(this.options.minWidth * 0.5),
				'width': this.options.minWidth
			}
		}).inject(this.overlay, 'after').setStyle('top', document.getScroll().y + this.options.top + 'px').set('morph', {
			'duration': 'short'
		});

		if(!this.options.allowSingleImage || link.rel != this.options.rel) {
			this.prevLink = new Element('a', {
				'id': 'mooViewPrevLink',
				'href': 'javascript:void(0)'
			}).inject(this.center);

			this.nextLink = new Element('a', {
				'id': 'mooViewNextLink',
				'href': 'javascript:void(0)'
			}).inject(this.center);
		}

		this.image = new Element('div', {
			'id': 'mooViewImage',
			'styles': {
				'height': this.options.minHeight
			}
		}).inject(this.center).set('morph', {
			'duration': 'short',
			'onComplete': function() {
				this.open();
			}.bind(this)
		}).set('opacity', 0);

		this.bottom = new Element('div', {
			'id': 'mooViewBottom'
		}).inject(this.image, 'after');

		new Element('a', {
			'id': 'mooViewClose',
			'href': 'javascript:void(0)'
		}).inject(this.bottom).addEvent('click', this.close.bind(this));

		this.caption = new Element('div', {
			'id': 'mooViewCaption'
		}).inject(this.bottom);

		this.number = new Element('div', {
			'id': 'mooViewNumber'
		}).inject(this.bottom);

	 	new Element('div', {
			'styles': {
				'clear': 'both',
				'height': '1px',
				'line-height': '0',
				'overflow': 'hidden'
			}
		}).inject(this.bottom);

		// open clicked image
		for(var i = 0; i < this.images[link.rel].length; i++) {
			if(this.images[link.rel][i][0].href == link.href) {
				this.activeImage = i;
				this.activeImageTitle = this.images[link.rel][i][1];
				this.activeImageRel = link.rel;
				this.preload = new Image();
				this.preload.onload = this.resize.bind(this);
				this.preload.onerror = this.close.bind(this);
				this.preload.src = this.images[link.rel][i][0].href;
				break;
			}
		}
		return false;
	},

	resize: function() {
		this.center.morph({
			'margin-left': -(Math.max(this.options.minWidth, this.preload.width) * 0.5),
			'width': Math.max(this.options.minWidth, this.preload.width),
			'top': document.getScroll().y + this.options.top + 'px'
		});

		this.image.morph({
			'height': Math.max(this.options.minHeight, this.preload.height)
		});
	},

	open: function() {
		// stop second morph onComplete
    	if(!this.preload) return false;

		this.center.removeClass('mooViewLoading');

		this.image.setStyles({
			'background-image': 'url(' + this.preload.src + ')'
		}).morph({
			'opacity': 1
		});

		this.caption.set('html', this.activeImageTitle || '').setStyle('display', this.activeImageTitle ? 'block' : 'none');

		// if not single image and more than 1 image in group
		if((!this.options.allowSingleImage || this.activeImageRel != this.options.rel) && this.images[this.activeImageRel].length > 1) {
			this.number.set('html', 'Изображение <b>' + (this.activeImage + 1) + '</b> из <b>' + this.images[this.activeImageRel].length + '</b>').setStyle('display', 'block');

			if(this.options.loopImages) {
				this.prevLink.setStyles({
					'height': Math.max(this.options.minHeight, this.preload.height),
					'display': 'block'
				}).addEvent('click', this.prev.bind(this));

				this.nextLink.setStyles({
					'height': Math.max(this.options.minHeight, this.preload.height),
					'display': 'block'
				}).addEvent('click', this.next.bind(this));
			}
			else {
				if(this.activeImage > 0) this.prevLink.setStyles({
					'height': Math.max(this.options.minHeight, this.preload.height),
					'display': 'block'
				}).addEvent('click', this.prev.bind(this));

				if(this.activeImage < this.images[this.activeImageRel].length - 1) this.nextLink.setStyles({
					'height': Math.max(this.options.minHeight, this.preload.height),
					'display': 'block'
				}).addEvent('click', this.next.bind(this));
			}
		}
		else this.number.setStyle('display', 'none');

		this.bottom.set('opacity', 1);

		this.preload = null;

		this.overlay.setStyle('height', document.getScrollSize().y);

		return false;
	},

	prev: function() {
		if(this.options.loopImages) {
			return (this.activeImage - 1 < 0) ? this.change(this.images[this.activeImageRel].length - 1) : this.change(this.activeImage - 1);
		}
		else {
			return this.change(this.activeImage - 1);
		}
	},

	next: function() {
		if(this.options.loopImages) {
			return (this.activeImage >= this.images[this.activeImageRel].length - 1) ? this.change(0) : this.change(this.activeImage + 1);
		}
		else {
			return this.change(this.activeImage + 1);
		}
	},

	change: function(imageNum) {
		if(imageNum < 0 || imageNum >= this.images[this.activeImageRel].length) {
			return false;
		}

		this.bottom.set('opacity', 0);
		this.image.setStyle('background-image', '').set('opacity', 0);
		this.center.addClass('mooViewLoading');
		this.nextLink.removeEvents();
		this.prevLink.removeEvents();
		this.prevLink.style.display = this.nextLink.style.display = 'none';
		this.activeImage = imageNum;
		this.activeImageTitle = this.images[this.activeImageRel][imageNum][1];
		this.preload = new Image();
		this.preload.onload = this.resize.bind(this);
		this.preload.src = this.images[this.activeImageRel][imageNum][0].href;
		return false;
	},

	close: function() {
		this.overlay.destroy();
		this.center.destroy();

		window.removeEvent('keydown', this.keyboardListener);
		window.removeEvent('mousewheel', this.mouseListener);

		// ie6 selects
		if(Browser.ie6) {
			$$('select').each(function(el) {
				el.style.visibility = '';
			});
		}

		// flash
		$$('object, embed').each(function(el) {
			el.style.visibility = '';
		});

		return false;
	} 

});

window.addEvent('domready', function() {
	new mooView();
});
