/*
Lightbox
Copyright(c) 2008, Skalpel.

Author : Michael
michael@skalpel.fr

Note : 
	- Version Alpha
ToDo :
	- Mieux commenter le code
	- Rajouter fonctionnalit�s (contenu ajax / vid�o flv ?)
	- Tester d'avantage et am�liorer ....
*/

window.addEvent('domready', function() {
	new SKjs.LightBox($$('a[rel=lightbox]'));
});
/* 
Class : SKjs.LightBox
	- Gestion de m�dias et formulaires en Lightbox
Arguments : 
	options {object} - Objet Options

Options :
	size {Object} - Taille initiale de la lightbox
	handler {Dom}
	overlay {Boolean}
	fixed {Boolean}
	parse {Boolean}
	openFromLink {Boolean}
	showTitle {Boolean}
	showNumbers {Boolean}
	showControls {Boolean}
	onOpen {Function}
	onClose {Function}
	onUpdate {Function}
	onResize {Function}
	onMove {Function}
*/
SKjs.LightBox = new Class ({
	Implements: [Events, Options],
	options: {
		size: {x: 400, y: 250},
		handler: 'iframe',
		overlay: true,
		overlayFx: false,
		parse: 'rel',
		fixed: false,
		openFromLink: true,
		showTitle: true,
		showNumbers: true,
		showNav: true,
		onOpen: $empty,
		onClose: $empty,
		onUpdate: $empty,
		onResize: $empty,
		onMove: $empty
	},
	
	initialize: function(selector, options) {
		this.setOptions(options);
		
		this.dom = {};
		this.fx = {};
		this.index;
		this.openClosePos = {};
		this.selector = ($type(selector) == 'array') ? selector : [selector];
		this.opened = false;
		
		if(!$('lightbox')) this.initDOM();
		else this.retrieveDOM();
		
		this.initFX();
		this.apply();
	},
	
	/*
	Property :
		Creation des elements DOM
	*/
	initDOM: function() {
		// Overlay
		if(this.options.overlay) {
			this.dom.overlay = new Element('div', {
				'id': 'overlay',
				'styles': {
					'top': 0,
					'left': 0,
					'width': '100%',
					'backgroundColor': '#000000',
					'opacity': 0
				}
			}).inject(document.body).addEvent('click', this.close.bind(this));
		}
		
		// Box
		this.dom.box = new Element('div', {'id': 'lightbox'}).inject(document.body);
		this.dom.content = new Element('div', {'class': 'content'}).inject(this.dom.box);
		this.dom.closeBtn = new Element('div', {'class': 'closeBtn'}).inject(this.dom.box).addEvent('click', this.close.bind(this));
		this.dom.controls = new Element('div', {'class': 'controls'}).inject(this.dom.box);
		
		this.dom.navPrevious = new Element('div', {'class': 'previousBtn', 'styles': {'display': 'none'}}).inject(this.dom.controls).addEvent('click', this.previous.bind(this));
		this.dom.navNext = new Element('div', {'class': 'nextBtn', 'styles': {'display': 'none'}}).inject(this.dom.controls).addEvent('click', this.next.bind(this));
		
		this.dom.title = new Element('div', {'class': 'title', 'styles': {'display': 'none'}}).inject(this.dom.controls);
		this.dom.numbers = new Element('div', {'class': 'numbers', 'styles': {'display': 'none'}}).inject(this.dom.controls);
		
		// Options
		if(this.options.showNav) {
			this.dom.navPrevious.setStyle('display', 'block');
			this.dom.navNext.setStyle('display', 'block');
		}
		if(this.options.showTitle) this.dom.title.setStyle('display', 'block');
		if(this.options.showNumbers) this.dom.numbers.setStyle('display', 'block');
		
		if((this.selector.length == 1 || !this.options.showNav) && this.options.showTitle) this.dom.title.setStyle('margin-left', '0');
		
		// Events
		if(Browser.Engine.trident) window.addEvent('domready', this.loadDOM.bind(this));
		else window.addEvent('load', this.loadDOM.bind(this));
		
		window.addEvent('scroll', this.move.bind(this));
		window.addEvent('resize', this.winResize.bind(this));
		
		this.reset();
	},
	/*
	Property :
	*/
	retrieveDOM: function() {
		// Overlay
		if(this.options.overlay) {
			if($('overlay')) {
				this.dom.overlay = $('overlay').addEvent('click', this.close.bind(this));
			} else {
				this.dom.overlay = new Element('div', {
					'id': 'overlay',
					'styles': {
						'top': 0,
						'left': 0,
						'width': '100%',
						'backgroundColor': '#000000',
						'opacity': 0
					}
				}).inject('before', $('lightbox')).addEvent('click', this.close.bind(this));
			}
		}
		
		// Box
		this.dom.box = $('lightbox');
		this.dom.content = $('lightbox').getElement('div.content');
		this.dom.closeBtn = $('lightbox').getElement('div.closeBtn').addEvent('click', this.close.bind(this));
		this.dom.controls = $('lightbox').getElement('div.controls');
		
		this.dom.navPrevious = $('lightbox').getElement('div.previousBtn').addEvent('click', this.previous.bind(this));
		this.dom.navNext = $('lightbox').getElement('div.nextBtn').addEvent('click', this.next.bind(this));
		
		this.dom.title = $('lightbox').getElement('div.title');
		this.dom.numbers = $('lightbox').getElement('div.numbers');
		
		// Options
		if(this.options.showNav) {
			this.dom.navPrevious.setStyle('display', 'block');
			this.dom.navNext.setStyle('display', 'block');
		}
		if(this.options.showTitle) this.dom.title.setStyle('display', 'block');
		if(this.options.showNumbers) this.dom.numbers.setStyle('display', 'block');
		
		if((this.selector.length == 1 || !this.options.showNav) && this.options.showTitle) this.dom.title.setStyle('margin-left', '0');
		
		// Events
		if(Browser.Engine.trident) window.addEvent('domready', this.loadDOM.bind(this));
		else window.addEvent('load', this.loadDOM.bind(this));
		
		window.addEvent('scroll', this.move.bind(this));
		window.addEvent('resize', this.winResize.bind(this));
		
		this.reset();
	},
	/*
	Property :
	*/
	loadDOM: function() {
		// Overlay
		if(this.options.overlay) this.dom.overlay.setStyle('height', window.getScrollSize().y);
	},
	/*
	Property :
	*/
	initFX: function() {
		this.fx.overlay = new Fx.Tween(this.dom.overlay, {
			property: 'opacity',
			duration: (this.options.overlayFx) ? 750 : 10
		});
		this.fx.win = new Fx.Morph(this.dom.box, {
			duration: 750,
			transition: 'sine:in:out'
		});
		this.fx.content = new Fx.Tween(this.dom.content, {
			property: 'opacity',
			duration: 250
		});
		this.fx.move = new Fx.Tween(this.dom.box, {
			link: 'cancel',
			property: 'top',
			duration: 250
		});
	},
	
	/*
	Property :
	*/
	apply: function() {
		this.selector.each(function(item, key) {
			item.store('index', key);
			item.addEvent('click', this.open.bindWithEvent(this, [item]));
		}, this);
	},
	/*
	Property :
	*/
	reset: function() {
		this.dom.box.setStyles({
			'opacity': 0,
			'display': 'none'
		});
		this.dom.controls.setStyle('display', 'none');
		if(this.options.showNav) {
			this.dom.navPrevious.removeClass('disabled');
			this.dom.navNext.removeClass('disabled');
		}
		this.dom.content.empty();
		this.opened = false;
	},
	
	/*
	Property :
	*/
	open: function(e, el) {
		var e = new Event(e).stop();
		this.fireEvent('onOpen');
		
		this.opened = true;
		this.index = el.retrieve('index');
		
		this.openClosePos = this.getOpenClosePos(el);
		this.dom.box.setStyles(this.openClosePos);
		this.dom.box.setStyles({
			'opacity': 0,
			'display': 'block'
		});
		
		var winFX = {
			'width': this.options.size.x,
			'height': this.options.size.y,
			'top': (window.getSize().y / 2) - (this.options.size.y / 2) + window.getScroll().y,
			'left': (window.getSize().x / 2) - (this.options.size.x / 2),
			'opacity': [0, 1]
		};
		
		// Etapes : Win FX, Load content
		var chain = new Chain();
		chain.chain(function() { 
			this.fx.win.start(winFX).chain(function() {
				this.load(this.index);
			}.bind(this));
		 }.bind(this));
		
		if(this.options.overlay) {
			// Etapes : Overlay FX, Win FX, Load content
			this.fx.overlay.start(0.7).chain(function() { chain.callChain(); });
		} else {
			chain.callChain();
		}
	},
	/*
	Property :
	*/
	close: function() {
		if(this.opened) {
			this.opened = false;
			this.fireEvent('onClose');
			
			// Content
			this.fx.content.start(1, 0).chain(function() {
				// Win
				this.fx.win.start($merge(this.openClosePos, {opacity: [1, 0]})).chain(function() {
					// Overlay 
					if(this.options.overlay) {
						this.fx.overlay.start(0).chain(function() { this.reset(); }.bind(this));
					} else {
						// Reset
						this.reset();
					}
				}.bind(this));
			}.bind(this));			
		}
	},
	/*
	Property :
	*/
	previous: function() {
		if(this.index > 0) {
			this.index--;
			this.fx.content.start(0).chain(function() {
				this.dom.content.empty();
				this.load(this.index);
			}.bind(this));
		}
	},
	/*
	Property :
	*/
	next: function() {
		if(this.index < this.selector.length -1) {
			this.index++;
			this.fx.content.start(0).chain(function() {
				this.dom.content.empty();
				this.load(this.index);
			}.bind(this));
		}
	},
	/*
	Property :
	*/
	move: function() {
		if(this.opened) {
			// Lightbox
			if(!this.options.fixed) {
				this.fireEvent('onMove');
				this.fx.move.start((window.getSize().y / 2) - (this.dom.content.getSize().y / 2) + window.getScroll().y);
			}
		}
	},
	/*
	Property :
	*/
	winResize: function() {
		if(this.opened) {
			// Lightbox
			this.dom.box.setStyles({
				'top': (window.getSize().y /2) - (this.dom.content.getSize().y / 2) + window.getScroll().y,
				'left': (window.getSize().x / 2) - (this.dom.content.getSize().x / 2)
			});
		}
	},
	/*
	Property :
	*/
	getOpenClosePos: function(el) {
		var openClosePos = {};
		
		if(this.options.openFromLink) {
			if(el.getFirst()) {
				openClosePos = {
					'width': el.getFirst().getCoordinates().width,
					'height': el.getFirst().getCoordinates().height,
					'top': el.getFirst().getCoordinates().top,
					'left': el.getFirst().getCoordinates().left
				};
			} else {
				openClosePos = {
					'width': el.getCoordinates().width,
					'height': el.getCoordinates().height,
					'top': el.getCoordinates().top,
					'left': el.getCoordinates().left
				};
			}
		} else {
			openClosePos = {
				'width': this.options.size.x,
				'height': this.options.size.y,
				'top': (window.getSize().y / 2) - (this.options.size.y / 2),
				'left': (window.getSize().x / 2) - (this.options.size.x / 2)
			};
		}
		return openClosePos;
	},
	/*
	Property :
	*/
	load: function(index) {
		this.fireEvent('onUpdate');
		this.dom.box.addClass('loading');
		this.dom.content.setStyle('opacity', 0);
		this.getContent(index);
	},
	/*
	Property :
	*/
	getContent: function(index) {
		// Chargement Contenu
		this.setContentType(this.selector[index]);
		
		// Controls
		if(this.options.showTitle || this.options.showNav || this.options.showNumbers) this.dom.controls.setStyle('display', 'block');
		// Title
		if(this.options.showTitle) {
			if(this.selector[index].getProperty('title')) this.dom.title.set('html', this.selector[index].getProperty('title'));
			else this.dom.title.set('html', '&nbsp;');
		}
		// Numbers
		if(this.options.showNumbers) {
			var numbers = (index + 1) +' sur '+ this.selector.length;
			this.dom.numbers.set('html', numbers);
		}
		// Nav
		if(this.options.showNav) {
			if(index == 0) {
				this.dom.navPrevious.addClass('disabled');
				this.dom.navNext.removeClass('disabled');
			} else if(index == this.selector.length -1) { 
				this.dom.navPrevious.removeClass('disabled');
				this.dom.navNext.addClass('disabled');
			} else {
				this.dom.navPrevious.removeClass('disabled');
				this.dom.navNext.removeClass('disabled');
			}
		}
	},
	/*
	Property :
	*/
	setContentType: function(link) {
		var size;
		var ext = link.getProperty('href').substr(link.getProperty('href').lastIndexOf('.')+1).toLowerCase();
		
		switch(ext) {
			case 'jpg':
			case 'gif':
			case 'png':
				this.loadImage(link);
				break;	
				
			default:
				var handler = this.options.handler.toLowerCase();
				var obj = null;
				
				if(this.options.parse) {
					obj = link.getProperty(this.options.parse);
					if(obj) {
						obj = JSON.decode(obj, false);
						handler = (obj.handler) ? obj.handler.toLowerCase() : handler;
						
					}
				}
				switch(handler) {
					//case 'ajax': this.loadAjax(link, obj); break;
					case 'iframe': this.loadIframe(link, obj); break;
				}
				break;
		}
	},
	/*
	Property :
	*/
	resize: function(args) {
		this.fireEvent('onResize');
		this.dom.content.adopt(args.dom);
		
		this.fx.win.start({
			'width': args.width,
			'height': args.height,
			'top': (window.getSize().y / 2) - (args.height / 2) + window.getScroll().y,
			'left': (window.getSize().x / 2) - (args.width / 2),
			'opacity': 1
		}).chain(function() { this.dom.box.removeClass('loading'); this.fx.content.start(1); }.bind(this));
	},
	
	
	/*
	Property :
	*/
	loadImage: function(link) {
		var self = this;
		var contentToLoad = new Asset.image(link, {
			onload: function() {
				self.resize({'width': this.width, 'height': this.height, 'dom': this});
			}
		});
	},
	/*
	Property :
	*/
	loadIframe: function(link, obj) {
		var iframeWidth = (obj && obj.size.x) ? obj.size.x : this.options.size.x;
		var iframeHeight = (obj && obj.size.y) ? obj.size.y : this.options.size.y;
		var contentToLoad = new Element('iframe', {
			src: link.getProperty('href'),
			frameBorder: 0,
			width: iframeWidth,
			height: iframeHeight
		});
		this.resize({'width': iframeWidth, 'height': iframeHeight, 'dom': contentToLoad});
	}
});
