/*
Script: RokZoom.js
	RokZoom, a derivative from Slimbox <http://www.digitalia.be/software/slimbox>

Author: 
	Olmo Maldonado, <http://olmo-maldonado.com/>

License:
	MIT
*/
var RokZoom = new Abstract({
	options: {
		imageDir: 'images/',
		resizeFX: {
			duration: 2000,
			transition: Fx.Transitions.Expo.easeOut,
			wait: false
		},
		opacityFX: {
			wait: false	
		},
		shadowFX: {
			duration: 350,
			wait: false
		},
		
		onClick: Function.empty,
		onClose: Function.empty
	},
	
	init: function(options){
		this.setOptions(options);

		this.getLinks();
		this.createElements();
		
		this.fx = {
			resize: this.center.effects(this.options.resizeFX),
			bottom: this.bottom.effect('top', this.options.captionFx),
			shadow: this.shadow.effect('opacity', this.options.shadowFx)
		};
	},
	
	getLinks: function() {
		this.anchors = [];
		$$(document.links).each(function(el){
			if (el.rel && el.rel.test(/^RokZoom/i)){
				el.onclick = this.click.bind(this);
				this.anchors.push(el);
			}
		}, this);
	},
	
	createElements: function() {
		$(document.body).adopt(
			new Element('div', {'id': 'rbCenter'}),
			new Element('div', {'id': 'rbLinks'}).adopt(
				new Element('div', {
					'id': 'rbPrevLink',
					'events': {'click': this.previous.bind(this)}
				}).adopt(
					new Element('img', {
						'src': 'images/spacer.gif',
						'styles': {
							'width': '100%',
							'height': '100%'
						},
						'events': {
							'mouseenter': function() {
								this.parentNode.addClass('hover');
							},
							'mouseleave': function() {
								this.parentNode.removeClass('hover');	
							}	
						}	
					})
				),
				new Element('div', {
					'id': 'rbNextLink',
					'events': {'click': this.next.bind(this)}
				}).adopt(
					new Element('img', {
						'src': 'images/spacer.gif',
						'styles': {
							'width': '100%',
							'height': '100%'
						},
						'events': {
							'mouseenter': function() {
								this.parentNode.addClass('hover');
							},
							'mouseleave': function() {
								this.parentNode.removeClass('hover');	
							}	
						}	
					})
				)
			),
			new Element('div', {'id': 'rbBottom'}).adopt(
				new Element('div', {
					'id': 'rbCloseLink',
					'events': {'click': this.close.bind(this)}
				}),
				new Element('div', {'id': 'rbCaption'}),
				new Element('div', {'id': 'rbNumber'}),
				new Element('div', {'styles': {'clear': 'both'}})
			)
		);
		
		['center', 'links', 'prevLink', 'nextLink', 'bottom', 'caption', 'number'].each(function(prop) {
			this[prop] = $('rb' + prop.capitalize());
			if(!(/caption|number|/).test(prop)) this[prop].setStyle('display', 'none');
		}, this);
		
		if(!Client.Engine.ie6) this.createShadows();
		else this.shadow = new Element('div', {'id': 'rbShadow'}).injectInside(document.body);
		
	},
	
	createShadows: function() {
		this.shadow = new Element('div', { 
			'id': 'rbShadow', 
			'styles': {
				'display': 'none'
			}
		}).adopt(
			new Element('table', {
				'styles': {
					'width': '100%',
					'height': '100%',
					'border-collapse': 'collapse'
				},
				'cellspacing': 0,
				'cellpadding': 0,
				'border': 0
			})
		);
		if(Client.Engine.ie) this.shadow.getElement('table').adopt(new Element('tbody'));
		
		var spacer = new Element('img', {
			'width': 1,
			'height': 1,
			'styles': {'display': 'block'}
		});
		
		var rows = [], col, l = 1;
		for(var i = 0; i < 3; i++) {
			rows[i] = new Element('tr', { 
				'styles': {'height': (i == 0) ? 25 : (i == 2) ? 26 : ''}
			});
			
			for(var j = 1; j <= 3; j++, l++) {
				col = j == 1 || j == 3;
				if(i == 1) col = !col;
				if(i == 1 && j == 2) l--;
				
				rows[i].adopt(
					new Element('td', {
						'styles': {
							'width': (col) ? (i == 2) ? 26 : 27 : '',
							'background': 'center center transparent url(' + ((!col) ? this.options.imageDir + 'zoom-shadow' + l + '.png' : '') + ')',
							'padding': 0,
							'margin': 0
						}
					}).adopt(
						spacer.clone().setProperties({
							'width': (col) ? 27 : 1,
							'height': (col) ? i == 2 ? 26 : 25 : 1,
							'src': this.options.imageDir + ((col) ? 'zoom-shadow' + l + '.png' : 'spacer.gif')
						})
					)	
				);
			}
		}
		
		rows[1].getElements('td')[1].set({
			'styles': { 
				'width': '', 
				'background': '#fff'
			},
			'bgcolor': '#fff',
			'height': '100%',
			'width': '100%'	
		}).empty().adopt(
			spacer.clone().set({ 
				'width': 1,
				'height': 1,
				'src': this.options.imageDir + 'spacer.gif'
			})
		);
		
		this.shadow.getElement(Client.Engine.ie ? 'tbody' : 'table').adopt(rows);
		
		$(document.body).adopt(this.shadow);
	},
	
	click: function(e){
		e = new Event(e).stop();
		this.fireEvent('onClick', [e]);
		
		this.called = false;
		this.origin = $(e.target);
		
		var link = e.target.parentNode;
		if (link.rel.length == 7) this.show(link.href, link.title);
		else {
			var j, imageNum, images = [];
			this.anchors.each(function(el){
				if (el.rel == link.rel){
					for (j = 0; j < images.length; j++) if(images[j][0] == el.href) break;
					if (j == images.length){
						images.push([el.href, el.title]);
						if (el.href == link.href) imageNum = j;
					}
				}
			}, this);
			
			this.open(images, imageNum);
		}
	},
	
	show: function(url, title){
		this.open([[url, title]], 0);
	},

	open: function(images, imageNum){
		this.images = images;
		this.setup(true);
		this.changeImage(imageNum);
	},
	
	setup: function(open){
		$$('object').extend(Client.Engine.ie ? $$('select') : []).each(function(el){ 
			el.setStyle('visibility', open ? 'hidden' : 'visible'); 
		});
		
		document[open ? 'addEvent' : 'removeEvent']('keyup', this.keyboardListener.bind(this));
	},

	keyboardListener: function(event){
		switch (event.code){
			case 27: case 88: case 67: this.close(); break;
			case 37: case 80: this.previous(); break;	
			case 39: case 78: this.next();
		}
	},
	
	previous: function(){
		if (this.activeImage < 0 || this.activeImage >= this.images.length) return;
		this.origin = this.anchors[this.anchors.indexOf(this.origin.getParent()) - 1].getElement('img');
		this.changeImage(this.activeImage - 1);
	},

	next: function(){
		if (this.activeImage < 0 || this.activeImage >= this.images.length) return;
		this.origin = this.anchors[this.anchors.indexOf(this.origin.getParent()) + 1].getElement('img');
		this.changeImage(this.activeImage + 1);
	},
	
	changeImage: function(imageNum){
		this.activeImage = imageNum;
		
		this.turnOff();
		this.coord = this.origin.getCoordinates();
		
		this.center.empty().set({
			'class': 'rbLoading',
			'styles': $merge(this.coord, {
				'display': 'block',
				'opacity': 1
			})
		});
		
		if(this.preload) {
			this.preload.onload = Class.empty;
			this.preload = null;
		}
		
		this.preload = new Asset.image(this.images[imageNum][0], {
			onload: this.startEffect.bind(this)	
		});
	},
	
	startEffect: function(){
		if(this.called) return;		
		this.called = true;
		
		this.image = this.preload.inject(this.center);
		this.size = { 
			'height': this.image.height,
			'width': this.image.width
		};
		
		this.image.set({
			'id': 'rbImage',
			'width': this.coord.width,
			'height': this.coord.height
		});
		
		this.bottom.setStyle('width', this.size.width);
		$$([this.prevLink, this.nextLink]).setStyle('height', this.size.height);
		
		this.caption.setHTML(this.images[this.activeImage][1] || '&nbsp;');
		this.number.setHTML((this.images.length == 1) ? '' : 'Image ' + (this.activeImage + 1) + ' of ' + this.images.length);
		
		this.fx = $merge(this.fx, {
			width: new Fx.Property(this.image, 'width', this.options.resizeFX), 
			height: new Fx.Property(this.image, 'height', this.options.resizeFX),
			opac: new Fx.Style(this.center, 'opacity', this.options.opacityFX)
		});
		
		if(this.group) this.group.removeEvent('onComplete');
		this.group = new Group(this.fx.width, this.fx.height, this.fx.resize, this.fx.opac).addEvent('onComplete', this.openFX.bind(this));
		
		this.center.set({
			'class': '',
			'styles': {
				'opacity': 0,
				'width': this.size.width,
				'height': this.size.height,
				'top': this.coord.top - this.image.getStyle('padding-top').toInt(),
				'left': this.coord.left - this.image.getStyle('padding-left').toInt()
			}
		});
		
		this.bottom.setStyles({
			'opacity': 0,
			'display': 'block'
		});
		
		this.fx.width.start(this.coord.width, this.size.width);
		this.fx.height.start(this.coord.height, this.size.height);
		this.fx.opac.start(1);
		this.fx.resize.start({
			'top': [this.coord.top, Math.round(0.5 * (Client.getHeight() - (this.size.height + this.bottom.offsetHeight)) + Client.getScrollTop())],
			'left': [this.coord.left, Math.round(0.5 * (Client.getWidth() - this.size.width) + Client.getScrollLeft())]
		});
	},
	
	openFX: function() {
		this.called = false;
		
		var coord = this.image.getCoordinates();
		this.bottom.setStyles({
			'top': coord.top + coord.height,
			'left': coord.left,
			'opacity': 1
		});
		this.links.setStyles(coord);
		
		this.fx.bottom.set(this.bottom.offsetTop - this.bottom.offsetHeight).start(this.bottom.offsetTop + this.bottom.offsetHeight).chain(function() {
			this.links.setStyle('display', 'block');
			if (this.activeImage) this.prevLink.setStyle('display', 'block');
			if (this.activeImage != (this.images.length - 1)) this.nextLink.setStyle('display', 'block');
			
			this.shadow.setStyles({
				'width': coord.width + 26,
				'height': coord.height + this.bottom.offsetHeight + 26,
				'left': coord.left - 13,
				'top': coord.top - 8,
				'opacity': 0,
				'display': 'block'
			});
			
			if(Client.Engine.ie7) this.shadow.getElement('table').setStyle('height', this.shadow.offsetHeight - 51);
			
			this.fx.shadow[!Client.Engine.ie ? 'start' : 'set'](1);
		}.bind(this));
		
	},
	
	close: function(e) {
		this.fireEvent('onClose', [e.stop()]);
		
		if(Client.Engine.ie) this.fx.shadow.set(0);
		this.fx.shadow.stop().start(0).chain(function() {
			this.fx.bottom.start(this.center.offsetTop + this.center.offsetHeight - this.bottom.offsetHeight).chain(function() {
				this.turnOff();
				this.coord = this.origin.getCoordinates();
				
				this.group.removeEvent('onComplete');
				this.group = new Group(this.fx.width, this.fx.height, this.fx.resize, this.fx.opac);
				this.group.addEvent('onComplete', function() {
					this.center.setStyles({
						'display': 'none',
						'width': this.coord.width,
						'height': this.coord.height
					});
					this.group.removeEvent('onComplete');
				}.bind(this));	
				
				this.fx.opac.start(0);
				this.fx.width.start(this.fx.width.now, this.coord.width);
				this.fx.height.start(this.fx.height.now, this.coord.height);
				this.fx.resize.start({
					'top': this.coord.top - this.image.getStyle('padding-top').toInt(),
					'left': this.coord.left - this.image.getStyle('padding-left').toInt()
				});
			}.bind(this));
		}.bind(this));
		
		this.setup(false);
	},
	
	turnOff: function() {
		this.els = this.els || $$([this.shadow, this.bottom, this.links, this.prevLink, this.nextLink]);
		this.els.setStyle('display', 'none');
	}
	
});
RokZoom.extend(new Events);
RokZoom.extend(new Options);

Group.implement({
	removeEvent: function(type) {
		this.instances.each(function(instance, i) {
			if(instance.$events[type]) instance.$events[type] = [];
		}, this);
		
		return this;	
	}
});

Fx.Property = new Class({
	Extends: Fx,
	initialize: function(el, property, options) {
		this.property = property;
		this.parent(el, options);
		this.element = $(el);
	},	
	
	increase: function() {
		$try(function() {
			this.element.setProperty(this.property, Math.round(this.now) + 'px');	
			this.element.setStyle(this.property, Math.round(this.now) + 'px');
		}, this);
	}
});
