var ReMooz = new Class({
	options: {
		id: null,
		url: null,
		opacityOptions: {},
		resizeOptions: {},
		positionToCenter: false,
		marginBox: 10,
		resize: true,
		resizeFactor: 0.8,
		resizeLimit: {x: 640, y: 640},
		zIndex: 41,
		zIndexFocus: 42
	},
	initialize: function(element, options) {
		this.element = $(element);
		this.setOptions(options);
		this.addEvent('onBlur', function() {
			this.focussed = false;
			this.box.setStyle('z-index', this.options.zIndex);
			this.box.removeClass('remo-box-focus');
		}.bind(this));
		this.addEvent('onFocus', function() {
			this.focussed = true;
			this.box.setStyle('z-index', this.options.zIndexFocus);
			this.box.addClass('remo-box-focus');
		}.bind(this));
		this.url = this.options.url || this.element.href;
		this.element.addClass('remo-zoom-in');
	},
	bindToElement: function(el) {
		($(el) || this.element).addEvent('click', function(e) {
			new Event(e).stop();
			this.open();
		}.bind(this));
	},
	open: function() {
		if (this.opened) return this;
		this.opened = true;
		if (!this.box) this.build();
		this.coords = this.element.getCoordinates();
		this.boxFx.set({
			opacity: 0,
			top: this.coords.top,
			left: this.coords.left,
			height: this.coords.height,
			width: this.coords.width
		}).start({'opacity': 0.7});
		this.box.setStyle('display', '');
		this.openImage();
		return this;
	},
	close: function() {
		if (!this.opened) return this;
		this.opened = false;
		ReMooz.close(this);
		if (this.loading) {
			this.box.setStyle('display', 'none');
			return this;
		}
		this.boxDrag.detach();
		this.btnClose.setStyle('display', 'none');
		if (this.boxFx.timer) this.boxFx.clearChain();
		this.coords = this.element.getCoordinates();
		this.boxFx.start({
			top: this.coords.top,
			left: this.coords.left,
			height: this.coords.height,
			width: this.coords.width
		}).chain(function() {
			this.image.src = null;
			this.element.setStyle('visibility', 'visible').focus();
			this.box.setStyle('display', 'none');
		}.bind(this));
		return this;
	},
	openImage: function() {
		var loader = new Image();
		this.loading = true;
		loader.onload = loader.onabort = loader.onerror = function() {
			var to = {x: loader.width, y: loader.height};
			this.loading = loader = loader.onload = loader.onabort = loader.onerror = null;
			if (!to.x || !this.opened) {
				this.close();
				return;
			}
			this.image.setStyle('visibility', 'visible');
			this.element.setStyle('visibility', 'hidden');
			this.boxFx.set({'opacity': 1})
			this.relativeResize(to);
		}.bind(this);
		this.image.src = this.url;
		loader.src = this.url;
		if (loader && loader.width && loader.onload) loader.onload();
	},
	relativeResize: function(to) {
		if (this.options.resize) {
			var max = this.options.resizeLimit || {
				x: window.getWidth() * this.options.resizeFactor,
				y: window.getHeight() * this.options.resizeFactor
			};
			for (var i = 0; i < 2; i++) {
				if (to.x > max.x) {
					to.y *= max.x / to.x;
					to.x = max.x;
				} else if (to.y > max.y) {
					to.x *= max.y / to.y;
					to.y = max.y;
				}
			}
		}
		return this.resizeTo({x: to.x.toInt(),y: to.y.toInt()});
	},
	resizeTo: function(to) {
		var box = window.getSize();
		var pos = {
			x: box.scroll.x + ((box.size.x - to.x) / 2).toInt(),
			y: box.scroll.y + ((box.size.y - to.y) / 2).toInt()
		};
		if (!this.options.positionToCenter) {
			pos.x = (this.coords.left + (this.coords.width / 2) - to.x / 2).toInt()
				.limit(box.scroll.x + this.options.marginBox, box.scroll.x + box.size.x - this.options.marginBox - to.x);
			pos.y = (this.coords.top + (this.coords.height / 2) - to.y / 2).toInt()
				.limit(box.scroll.y + this.options.marginBox, box.scroll.y + box.size.y - this.options.marginBox - to.y);
		}
		ReMooz.open(this);
		this.boxFx.start({
			//opacity: [0, 1],
			left: pos.x,
			top: pos.y,
			width: to.x,
			height: to.y
		}).chain(function() {
			this.boxDrag.attach();
			this.btnClose.setStyle('display', '');
		}.bind(this));
	},
	build: function() {
		this.box = new Element('div', {
			'class': 'remo-box',
			styles: {
				display: 'none',
				zIndex: this.options.zIndex
			},
			events: {
				mousedown: function(e) {
					if (!this.focussed && !this.loading) ReMooz.focus(this);
					else if (!this.dragging) this.close();
				}.create({bind: this, delay: 100})
			}
		}).inject(document.body);
		this.boxFx = this.box.effects({
			duration: 700,
			transition: Fx.Transitions.Quint.easeOut,
			wait: false
		});
		this.boxDrag = new Drag.Move(this.box, {
			snap: 0,
			onSnap: function() {
				this.dragging = true;
				this.box.addClass('remo-box-dragging');
			}.bind(this),
			onComplete: function() {
				this.dragging = false;
				this.box.removeClass('remo-box-dragging');
			}.create({bind: this, delay: 10})
		}).detach();
		this.btnClose = new Element('a', {
			'class': 'remo-btn-close',
			styles: {
				display: 'none'
			},
			events: {
				click: this.close.bind(this)
			}
		}).inject(this.box);

		this.buildImage();
	},
	buildImage: function() {
		this.image = new Element('img', {
			'class': 'remo-img',
			styles: {
				visibility: 'hidden'
			}
		}).inject(this.box);
	}
});
ReMooz.implement(new Events, new Options);
ReMooz.extendFactory = $extend;
ReMooz.extendFactory({
	options: {
		zIndex: 41,
		zIndexFocus: 42
	},
	opened: [],
	open: function(obj) {
		this.focus(obj);
	},
	close: function(obj) {
		var last = this.opened.length - 1;
		if (this.opened.indexOf(obj) == last) this.focus(this.opened[last - 1]);
		this.opened.remove(obj);
	},
	focus: function(obj) {
		var last = this.opened.getLast();
		if (!obj || last == obj) return;
		if (last) last.fireEvent('onBlur', [last], 10);
		obj.fireEvent('onFocus', [obj], 10);
		this.opened.remove(obj).push(obj);
	}
});
Element.extend({

	wrapIn: function(el){
		return $(el).injectAfter(this).adopt(this);
	}
});