/*
Script: MtLightbox
Version: 1.0
License: MIT-style license.
Copyright: Copyright (c) 2010 [Niklas Lehto].
Author: Niklas Lehto (http://www.mediatales.se).
Requires: Core 1.2.4, Loop
*/

var mtLightbox = new Class({
	Implements: [Options],
	options: {
		anchorClass: 'mtLightbox',
		wrapperId: 'mtlbWrapper',
		dimmerId: 'mtlbDimmer',
		dimmerOpacity: 0.9
	},

	initialize: function(options){
		this.setOptions(options);
		this.createElements();
		this.bindAnchors();
	},

	createElements: function(){
		var dimmer = new Element('div',{
			id: this.options.dimmerId,
			styles: {
				opacity: 0
			}
		}).inject($$('body')[0]);

		var wrapper = new Element('div',{
			id: this.options.wrapperId
		}).inject($$('body')[0]);

		var ajaxLoader = new Element('span',{
			id: 'ajaxLoader'
		}).inject(wrapper);

		var caption = new Element('div',{
			id: 'mtlbCaption',
			styles: {
				display: 'none',
				opacity: 0
			}
		}).inject(wrapper);

		var nav = new Element('div',{
			id: 'mtlbNav',
			styles: {
				display: 'none',
				opacity: 0
			}
		}).inject(wrapper);

		var navClose = new Element('span',{
			html: '&nbsp;',
			id: 'navClose',
			'class': 'mtlbNavClose',
			events: {
				click: function(){
					this.close();
				}.bind(this)
			}
		}).inject(nav);

		var navPlay = new Element('span',{
			html: '&nbsp;',
			id: 'navPlay',
			'class': 'mtlbGalleryNav',
			events: {
				click: function(){
					//
				}.bind(this)
			}
		});

		var navLast = new Element('span',{
			html: '&nbsp;',
			id: 'navLast',
			'class': 'mtlbGalleryNav',
			events: {
				click: function(){
					this.galleryNav('showLast');
				}.bind(this)
			}
		}).inject(nav);

		var navNext = new Element('span',{
			html: '&nbsp;',
			id: 'navNext',
			'class': 'mtlbGalleryNav',
			events: {
				click: function(){
					this.galleryNav('showNext');
				}.bind(this)
			}
		}).inject(nav);

		var navInfo = new Element('span',{
			id: 'navInfo',
			'class': 'mtlbGalleryNav'
		}).inject(nav);

		var navPrev = new Element('span',{
			html: '&nbsp;',
			id: 'navPrev',
			'class': 'mtlbGalleryNav',
			events: {
				click: function(){
					this.galleryNav('showPrev');
				}.bind(this)
			}
		}).inject(nav);

		var navFirst = new Element('span',{
			html: '&nbsp;',
			id: 'navFirst',
			'class': 'mtlbGalleryNav',
			events: {
				click: function(){
					this.galleryNav('showFirst');
				}.bind(this)
			}
		}).inject(nav);
	},

	bindAnchors: function(){
		$$('a.'+this.options.anchorClass).each(function(el){
			el.addEvent('click', function(event){
				event.preventDefault();
				el.blur(); // Prevent enterkey from firing the script
				this.setTopMargin();
				this.setup(el);
			}.bind(this));
		}, this);
	},

	setTopMargin: function(){
		// Get scroll value
		var scrollValue = window.getScroll().y;
		// Set top value
		$(this.options.wrapperId).setStyle('top',scrollValue + 60 + 'px');
	},

	setup: function(el){
		// Setup variables
		this.enableNavigation = false; // Allow navigation only when darkbox is fully loaded

		this.el = el;
		this.href = el.href;
		this.caption = el.title || el.name || false;
		this.galleryId = el.rel || false;
		if(this.galleryId){
			this.galleryImgs = $$('a.'+this.options.anchorClass).filter(function(value){
				return value.get('rel') == this.galleryId;
			}, this);
			this.currentIndex = this.galleryImgs.indexOf(this.el);
		}
		else {
			this.galleryImgs = this.currentIndex = null;
		}

		// Listen for resize and keydown events
		window.addEvent('resize', function(){
			this.updateWrapperPos();
		}.bind(this));
		document.addEvent('keydown', function(event){
			if(event.key == 'esc'){
				event.preventDefault(); // Prevents firefox from pausing playback of gif animations
				this.close();
			}
			if(event.key == 'w'){
				event.preventDefault();
				this.galleryNav('showFirst');
			}
			if(event.key == 's'){
				event.preventDefault();
				this.galleryNav('showLast');
			}
			if(event.key == 'left' || event.key == 'backspace' || event.key == 'a'){
				event.preventDefault();
				this.galleryNav('showPrev');
			}
			if(event.key == 'right' || event.key == 'space' || event.key == 'd'){
				event.preventDefault();
				this.galleryNav('showNext');
			}
		}.bind((this)));

		// Setup elements
		$(this.options.dimmerId).setStyle('display','block');
		$(this.options.dimmerId).set('tween', {
			duration: 400,
			onComplete: function(){
				$(this.options.wrapperId).setStyle('display','block');
				$('ajaxLoader').setStyle('display', 'inline');
				this.createImgEl();
			}.bind(this)
		}).tween('opacity', this.options.dimmerOpacity);
	},

	createImgEl: function(){
		this.img = new Asset.image(this.href, {
			id: 'mtlbImg',
			styles: {
				opacity: 0
			},
	 		onload: function(){
	 			this.prepareDisplay();
			}.bind(this)
		});
	},

	prepareDisplay: function(){
		this.img.inject($(this.options.wrapperId), 'top');
		this.imgDims = this.img.getStyles('height', 'width');
		// Hide ajax loader
		$('ajaxLoader').setStyle('display', 'none');
		this.updateWrapper();
	},

	calcPosData: function(){
		// Get window width
		var x = window.getSize().x.toInt();
		// Set negative margins only if windowsize is bigger than imgDims
		var posX = marginX = 0;
		if(x > this.imgDims['width'].toInt() + $(this.options.wrapperId).getStyle('padding-left').toInt() + $(this.options.wrapperId).getStyle('padding-right').toInt()){
			var marginX = -(this.imgDims['width'].toInt()/2) - $(this.options.wrapperId).getStyle('padding-left').toInt();
			var posX = '50%';
		}
		this.posData = {'posX': posX, 'marginX': marginX};
	},

	getDuration: function(){
		var currentWidth = $(this.options.wrapperId).getStyle('width').toInt();
		var newWidth = this.imgDims['width'].toInt();
		var widthDiff = (currentWidth > newWidth) ? currentWidth - newWidth : newWidth - currentWidth;
		return (widthDiff * 12).limit(250,750).round(); // make multiplier an option?
	},

	updateWrapper: function(){
		this.calcPosData();
		var duration = this.getDuration();
		$(this.options.wrapperId).set('morph', {
			duration: duration,
			onStart: function(){
				if(!$defined(this.currentPosX))
				{
					this.currentPosX = 50;
				}
				$(this.options.wrapperId).set('tween',{
					duration: duration,
					unit: '%'
				}).tween('left',this.currentPosX, this.posData['posX']);
			}.bind(this),
			onComplete: function(){
				this.img.set('tween',{
					duration: 750,
					onComplete: function(){
						$(this.options.wrapperId).set('tween',{
							duration: 500,
							onComplete: function(){
								// Setup navigation.
								if(this.galleryId){
									$('navInfo').set('html',this.currentIndex+1 +'/'+this.galleryImgs.length);
									$$('.mtlbGalleryNav').each(function(value){
										value.setStyle('display','inline');
									});
								}
								// Show nav and captions.
								if(this.caption){
									$('mtlbCaption').set({
										'html': this.caption,
										styles: {
											display: 'block'
										}
									});
								}
								$('mtlbNav').setStyle('display','block');
								$('mtlbNav').fade('in');
								$('mtlbCaption').fade('in');
								// Enable navigation when all elements are fully loaded
								this.enableNavigation = true;	
							}.bind(this)
						}).tween('height', this.imgDims['height'].toInt()+30);
					}.bind(this)
				}).tween('opacity', 1);
			}.bind(this)
		}).morph({
			width: this.imgDims['width'],
			height: this.imgDims['height'],
			'margin-left': this.posData['marginX']
		});
		// Remember the wrapper position for seamless tweens
		this.currentPosX = this.posData['posX'];
	},

	updateWrapperPos: function(){
		this.calcPosData();
		// Update Wrapper
		$(this.options.wrapperId).set({
			styles: {
				left: this.posData['posX'],
				'margin-left': this.posData['marginX']
			}
		});
	},

	galleryNav: function(cmd){
		if(!this.enableNavigation) return false;
		if((cmd == 'showFirst' || cmd == 'showPrev') && (this.galleryId && this.currentIndex > 0)){
			this.close(true);
			(cmd == 'showFirst') ? this.setup(this.galleryImgs[0])
			: this.setup(this.galleryImgs[this.currentIndex-1]);
		}
		if((cmd == 'showNext' || cmd == 'showLast') && (this.galleryId && this.currentIndex < this.galleryImgs.length-1)){
			this.close(true);
			(cmd == 'showLast') ? this.setup(this.galleryImgs[this.galleryImgs.length-1])
			: this.setup(this.galleryImgs[this.currentIndex+1]);
		}
	},

	close: function(flag){
		//Flag is not a very descriptive name now, is it? Change.
		if(!flag){
			$(this.options.wrapperId).set({
				styles: {
					display: 'none'
				}
			});
			$(this.options.dimmerId).set({
				styles: {
					opacity: 0,
					display: 'none'
				}	
			});
		}
		// Hide nav and caption
		$('mtlbNav').set({
			styles: {
				display: 'none',
				opacity: 0
			}
		});
		$('mtlbCaption').set({
			styles: {
				display: 'none',
				opacity: 0
			}
		});
		$$('.mtlbGalleryNav').each(function(value){
			value.setStyle('display','none');
		});
		// Clean up
		$('mtlbImg').destroy();
		window.removeEvents('resize');
		document.removeEvents('keydown');
	}
});

/*
Script: MtOverlay
Version: 1.0
License: MIT-style license.
Copyright: Copyright (c) 2010 [Niklas Lehto].
Author: Niklas Lehto (http://www.mediatales.se).
*/

var MtOverlay = new Class({

	Implements: [Options],

	options: {
		overlayId: 'overlay',
		opacity: '.5',
		zIndex: 1000
	},

	createOverlay: function(){
		//Create overlay
		if(!$(this.options.overlayId)){

			this.modalWrapper = new Element('div',{
				//Forces IE to play nice when using a container for Draggable elements 
				id: this.options.overlayId+'Wrapper',
				styles: {
					'position': 'absolute',
					'display': 'none',
					'z-index': this.options.zIndex
				}
			}).inject(document.body,'top');

			this.overlay = new Element('div',{
				id: this.options.overlayId,
				styles: {
					'display': 'none',
					'opacity': this.options.opacity,
					'z-index': this.options.zIndex+1
				}
			}).inject(this.modalWrapper);

			//Used to contrain dialogs (if moveable) within the viewport.
			this.dialogWrapper = new Element('div',{
				id: this.options.overlayId+'Dialogs',
				styles: {
					'z-index': this.options.zIndex+2
				}
			}).inject(this.modalWrapper);

		}
		else{
			this.modalWrapper = $(this.overlayId+'Wrapper');
			this.overlay = $(this.options.overlayId);
			this.dialogWrapper = $(this.options.overlayId+'Dialogs');
		}
	},

	showOverlay: function(){
		this.modalWrapper.setStyle('display','block');
		this.overlay.setStyle('display','block');
	},

	hideOverlay: function(){
		this.overlay.setStyle('display','none');
		this.modalWrapper.setStyle('display', 'none');
		this.forceOperaRepaint();
	},

	forceOperaRepaint: function(){
		if(Browser.Engine.presto){
			var margin = $(document.body).getStyle('margin-bottom');
			$(document.body).setStyle('margin-bottom',(margin.toInt()+100)+'px');
			(function(){ $(document.body).setStyle('margin-bottom',margin); }).delay(5);
		}
	},

	setPos: function(el){
		//Gather data
		elDims = el.getDimensions(true);
		windowDims = window.getSize();

		posX = windowDims.x/2 - elDims.x/2;
		posY = windowDims.y/2 - elDims.y/2;

		el.setStyles({
			'position': 'absolute',
			'left': posX+'px',
			'top': posY+'px'
		});
	}
});

/*
Script: MtDialog
Version: 1.0
License: MIT-style license.
Copyright: Copyright (c) 2010 [Niklas Lehto].
Author: Niklas Lehto (http://www.mediatales.se).
Script limitations: Currently not possible to stack dialogs. 
*/
var MtDialog = new Class({

	Implements: [Options,MtOverlay],

	options: {
		dialogId: 'mtDialog',
		title: 'Javascript-program',
		isMovable: true,
		okLabel: 'Ok',
		cancelLabel: 'Cancel'
	},

	initialize: function(options){
		this.setOptions(options);
		this.createOverlay();
		this.createDialog();
	},

	createDialog: function(){
		this.dialog = new Element('div', {
			id: this.options.dialogId,
			styles: {
				'display': 'none'
			}
		}).inject(this.dialogWrapper);

		this.header = new Element('div', {
			id: this.options.dialogId+'Header',
			html: '<span>'+this.options.title+'</span>'
		}).inject(this.dialog);

		this.close = new Element('span',{
			id: this.options.dialogId+'Close'
		}).inject(this.header);

		this.body = new Element('div', {
			id: this.options.dialogId+'Body'
		}).inject(this.dialog);

		if(this.options.isMovable){
			this.dialog.makeDraggable({
				container: this.dialogWrapper,
				handle: this.header
			});
		}
	},

	//Utility methods
	setMsg: function(msg){
		//Clear body
		this.body.set('html','');

		new Element('p',{
			html: msg
		}).inject(this.body);
	},

	setClass: function(className){
		this.dialog.erase('class').addClass(className);
	},

	show: function(ref){
		this.showOverlay();
		this.setPos(this.dialog);
		this.dialog.setStyle('display', 'block');

		if(ref=='prompt'){
			this.promptBox.focus();
			this.promptBox.select();
		}
		else{
			this.body.getElement('button').focus();
		}
	},

	hide: function(){
		this.dialog.setStyle('display','none');
		this.hideOverlay();
	},

	createButtons: function(optionsO){
		optionsO.each(function(value,index){
			new Element('button',{
				html: index,
				events: {
					click: function(){
						this.hide();
						value.call();
					}.bind(this)
				}
			}).inject(this.body);
		},this);
	},

	setClose: function(optionsO){
		var values = optionsO.getValues();
		var fn = values[values.length-1];

		//Clear events
		this.close.removeEvents('click');
		this.dialog.removeEvents('keydown');

		//Add events
		this.close.addEvent('click',function(){
			this.hide();
			if($type(fn)=='function') fn.call();
		}.bind(this));

		this.dialog.addEvent('keydown',function(e){
			if(e.key == 'esc'){
				this.hide();
				if($type(fn)=='function') fn.call();
			}
		}.bind(this));
	},

	//Dialog methods
	alert: function(msg,optionsO){
		optionsO = new Hash(optionsO);

		this.setMsg(msg);
		this.setClass('alert');
		//If object is passed as argument, create custom buttons
		if(optionsO.getLength()!=0){
			this.createButtons(optionsO);
		}
		else {
			new Element('button',{
			html: this.options.okLabel,
			events: {
				click: function(){
					this.hide();
				}.bind(this)
			}
			}).inject(this.body);
		}

		this.setClose(optionsO);


		this.show();
	},

	confirm: function(msg,optionsO){
		optionsO = new Hash(optionsO);

		this.setMsg(msg);
		this.setClass('confirm');
		this.createButtons(optionsO);
		this.setClose(optionsO);
		this.show();
	},

	prompt: function(msg,defaultValue,optionsO){
		optionsO = new Hash(optionsO);

		this.setMsg(msg);
		this.setClass('prompt');

		this.promptBox = new Element('input',{
			type: 'text',
			size: '20',
			value: defaultValue
		}).inject(this.body);

		this.createButtons(optionsO);
		this.setClose(optionsO);
		this.show('prompt');
	}
});
