/*** Abstract Dialog ***/
var AbstractDialog = Class.create({
	
	initialize: function(pane, width)
	{
		pane.setStyle({'display': 'none' });
		$(document.body).insert(pane);
		
		this.pane = pane;
		this.setWidth(width);
		this.overlay = Overlay.singleton();
		this.showing = false;
		
		Event.observe(document, "keydown",
		    function(event) {
		    	if (this.showing && event.keyCode == Event.KEY_ESC)
		    		this.close();
		    }.bind(this)
		);
		
		Event.observe(this.overlay.overlay, 'click', function() {
			if (this.showing)
				this.close();
		}.bind(this));
	}
	
	,show: function(options)
	{
		var self = this;
		
		if (! options) options = {};
		
		this.beforeShow(options);
		
		this.overlay.show();
		
		var dim = document.viewport.getDimensions();
		var offsetTop = document.viewport.getScrollOffsets().top;
		this.pane.style.left = (dim.width - this.width) / 2 + 'px';
		
		var top = Math.max(
			offsetTop + (dim.height - this.pane.getHeight()) / 3
			,50) + 'px'
			
		this.pane.style.top = top;
		
		new Effect.Appear(this.pane, { duration: 0.5, afterFinish: function() {
			this.afterShow(options);
			this.showing = true;
		}.bind(this)});
	}
	
	,close: function()
	{
		this.showing = false;

		this.beforeClose();
		
		this.overlay.close();
		new Effect.Fade(this.pane, {duration: 0.2, afterFinish: this.afterClose.bind(this)});
	}
	
	,setWidth: function(width)
	{
		if (! width)
			return;
			
		this.pane.setStyle({width: width + 'px'});
		this.width = width;
	}
	
	,setTransparant: function(transparant)
	{
		if (transparant)
		{
			this.pane.addClassName('window-dialog-transparant');
		}
		else
		{
			this.pane.removeClassName('window-dialog-transparant');			
		}
	}
	
	/** Callbacks **/
	,beforeShow: function(options) {}
	,afterShow: function(options) {}
	,beforeClose: function(options) {}
	,afterClose: function(options) {}
});

var Translations = Class.create(Hash, {
	initialize: function($super, data)
	{
		$super(data);
	},

	get: function($super, key)
	{
		var v = $super(key);
		return (! Object.isString(v)) ? key : v;
	}
});

var SignUpDialog = Class.create(AbstractDialog, {
	
	initialize: function($super, labels)
	{
		var self = this;
		labels = new Translations(labels);

		var pane;
		
		with ($E)
		{
			var buttonClose = a(
				{href: ''}
				,img({src: '/media/gfx/window_close.gif', 'class': 'button-close'})
			);
			
			Event.observe(buttonClose, 'click', function(event) {
				Event.stop(event);
				self.close();
			});

			var paragraphErrorMessage = p({'class':'error-message'});
			this.paragraphErrorMessage = paragraphErrorMessage;
			
			var inputNaam = input({'class': 'text', type: 'text', name: 'form_signup_naam'});
			this.inputNaam = inputNaam;
			
			var linkForgotPassword = a({href: ''}, labels.get('Wachtwoord vergeten?'));
			
			Event.observe(linkForgotPassword, 'click', function(event) {
				Event.stop(event);
				ForgotPasswordDialog.singleton().show();
				this.close();
			}.bind(this));
			
			pane = div(
				{'class': 'window-signup window-dialog'}
				,buttonClose
				,h1(labels.get('Inschrijven'))
				,p(labels.get('signup.explanation1')) // "Als u zich inschrijft bij Amsterdam Bright City meldt u zich aan voor de nieuwsbrief en kunt u reageren op artikelen en stellingen."
				,p(labels.get('signup.explanation2')) // "Na het inschrijven ontvangt u een bevestiging per e-mail.")
				,paragraphErrorMessage
				,fieldset(
					{'class': 'form'}
					,form(
						{method: 'post'}
						,h2(labels.get('Uw gegevens'))
						,ul(
							li(
								label(
									{'class': 'label'}
									,labels.get('Naam') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,inputNaam
							)

							,li(
								label(
									{'class': 'label'},
									labels.get('Geslacht') + ' ',
									span({'class':'error', 'style': 'display: none;'},"*")),
								select(
									{name: 'form_signup_geslacht'},
									option({value: 'm'}, labels.get('Man')),
									option({value: 'v'}, labels.get('Vrouw'))
								)
							)
							,li(
								label(
									{'class': 'label'},
									labels.get('Ik ben') + ' ',
									span({'class':'error', 'style': 'display: none;'},"*")),
								select(
									{name: 'form_signup_doelgroep'},
									option({value: 'student'}, 'Student'),
									option({value: 'young_professional'}, 'Young Professional (tot 35)'),
									option({value: 'professional'}, 'Professional (35+)')
								)
							),
							li(
								label(
									{'class': 'label'}
									,labels.get('Organisatie') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'text', name: 'form_signup_organisatie'})
							),
							li(
								label(
									{'class': 'label'}
									,labels.get('Geboortedatum') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'text', name: 'form_signup_geboortedatum', style: 'width: 120px;'})
								,div(small('(mm/dd/jjjj)'))
							),
							li(
								label(
									{'class': 'label'}
									,labels.get('Telefoonnummer') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'text', name: 'form_signup_telefoonnummer', style: 'width: 120px;'})
							)
						)
						,h2(labels.get('E-mailadres en wachtwoord'))
						,ul(
							li(
								label(
									{'class': 'label'}
									,labels.get('E-mail')
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'text', name: 'form_signup_email'})
							)
							,li(
								label(
									{'class': 'label'}
									,labels.get('Wachtwoord') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'password', name: 'form_signup_wachtwoord'})
							)
							,li(
								label(
									{'class': 'label'}
									,labels.get('Herhaal uw wachtwoord') + ' '
									,span({'class':'error', 'style': 'display: none;'},"*")
								)
								,input({'class': 'text', type: 'password', name: 'form_signup_wachtwoord_herhaal'})
							)
						),p(
							{'class': 'paragraph-button'}
							,input({type: 'submit', 'class': 'button', value: labels.get('Inschrijven') })
						)
						,input({type: 'hidden', name: 'action', value: 'signup'})
					)
				)
			)
		}
		
		$super(pane, 400);
	}
	
	,beforeShow: function(options)
	{
		var self = this;
		
		if (! options)
			options = {};
			
		var errorMessage, data = {}, errorFields = [];
		
		// set options
		with (options)
		{
			(errorMessage)
				? this.setErrorMessage(errorMessage)
				: this.setErrorMessage('');
				
			// mark error fields
			if (errorFields)
			{
				$A(errorFields).each(function(fieldName) {
					self.pane
						.select("INPUT[name='" + fieldName + "']")
						.first()
						.up("LI")
						.down("SPAN.error")
						.show();
				});
			}
			else
			{
				// hide all error fields
				self.pane.select("SPAN.error").invoke("hide");
			}
			
			if (data)
			{
				$H(data).each(function(pair)
				{
					var input = self.pane.select("*[name='form_signup_" + pair.key + "']").first();

					if (input.tagName == 'INPUT')
					{
						input.value = pair.value;
					}
					else if (input.tagName == 'SELECT')
					{
						input.select("OPTION[value='" + pair.value + "']").first().selected = true;
					}
				});
			}
			else
			{
				// no data given, clear form
				self.pane
					.select("INPUT[type='text']")
					.each(function(e){
						e.value = '';
					});
			}
		}
	}
	
	,afterShow: function()
	{
			
		// focus first field that contains an error, otherwise focus the first input
		var focused = false;
		
		this.pane
			.select("SPAN.error")
			.findAll(function(e) { return e.visible(); })
			.each(function(e) {
				e.up("LI").down("INPUT").focus();
				focused = true;
				throw $break;
			});
			
		if (! focused)
			this.inputNaam.focus();
	}
	
	
	,setErrorMessage: function(message)
	{
		this.paragraphErrorMessage.update(message);
	}
});

SignUpDialog.singleton = function(labels)
{
	if (! this.instance)
		this.instance = new SignUpDialog(labels);
		
	return this.instance;
}


var PlainDialog = Class.create(AbstractDialog, {
	
	initialize: function($super)
	{
		var self = this;
		
		var pane;
		
		with ($E)
		{
			var nodeText = div();
			
			this.nodeText = nodeText;
			
			pane = div(
				{'class': 'window-message window-dialog'}
				,nodeText
			);
		}
		
		$super(pane, 280);
	}
	
	,beforeShow: function(options)
	{
		var self = this;
		
		// remove old data
		this.nodeText.childElements().invoke("remove");
		
		if (! options)
			options = {};
			
		if (! options.width) options.width = null;
		if (! options.width) options.transparant = false;
			
		// apply properties
		with (options)
		{
			if (textNode)
				this.nodeText.insert(textNode);
				
			if (width)
				this.setWidth(width);
				
			if (transparant)
				this.setTransparant(true);
		}
	}
});

PlainDialog.singleton = function()
{
	if (! this.instance)
		this.instance = new PlainDialog();
		
	return this.instance;
}


/*** Message Dialog ***/

var MessageDialog = Class.create(AbstractDialog, {
	
	initialize: function($super)
	{
		var self = this;
		
		var pane;
		this.buttonCallback = null;
		
		with ($E)
		{
			var buttonClose = a(
				{href: ''}
				,img({src: '/media/gfx/window_close.gif', 'class': 'button-close'})
			);
			
			Event.observe(buttonClose, 'click', function(event) {
				Event.stop(event);
				self.close();
			});

			var nodeText = div();
			var nodeTitle = h1();
			var nodeButton = input({type: 'button', 'class': 'button'});
			
			Event.observe(nodeButton, 'click', function() {
				if (this.buttonCallback)
					this.buttonCallback();
			}.bind(this));
			
			this.nodeText = nodeText;
			this.nodeTitle = nodeTitle;
			this.nodeButton = nodeButton;
			
			pane = div(
				{'class': 'window-message window-dialog'}
				,buttonClose
				,nodeTitle
				,nodeText
				,p(nodeButton)
			);
		}
		
		$super(pane, 280);
	}
	
	,beforeShow: function(options)
	{
		var self = this;
		
		// remove old data
		this.nodeText.childElements().invoke("remove");
		this.nodeTitle.update("");
		this.nodeButton.setAttribute('value', '');
		this.buttonCallback = null;
		
		if (! options)
			options = {};
			
		if (! options.width) options.width = null;
		if (! options.width) options.transparant = false;
			
		// apply properties
		with (options)
		{
			if (title)
				this.nodeTitle.update(title);
				
			if (textNode)
				this.nodeText.insert(textNode);
				
			if (buttonCaption)
				this.nodeButton.value = buttonCaption;
				
			if (buttonHandler)
				this.buttonCallback = buttonHandler.bind(this);
				
			if (width)
				this.setWidth(width);
				
			if (transparant)
				this.setTransparant(true);
		}
	}
});

MessageDialog.singleton = function()
{
	if (! this.instance)
		this.instance = new MessageDialog();
		
	return this.instance;
}

var ForgotPasswordDialog = Class.create(AbstractDialog, {
	initialize: function($super)
	{
		var self = this;
		
		var pane;
		
		with ($E)
		{
			var buttonClose = a(
				{href: ''}
				,img({src: '/media/gfx/window_close.gif', 'class': 'button-close'})
			);
			
			Event.observe(buttonClose, 'click', function(event) {
				Event.stop(event);
				self.close();
			});

			var paragraphErrorMessage = p({'class':'error-message'});
			this.paragraphErrorMessage = paragraphErrorMessage;
			
			var inputEmail = input({'class': 'text', type: 'text', name: 'email'});
			this.inputEmail = inputEmail;
			
			pane = div(
				{'class': 'window-forgot-password window-dialog'}
				,buttonClose
				,h1("Wachtwoord vergeten?")
				,p('Als u uw wachtwoord bent vergeten, vul dan hieronder uw e-mailadres in. U ontvangt binnen enkele minuten een e-mail met daarin uw login gegevens.')
				,paragraphErrorMessage
				,fieldset(
					{'class': 'form'}
					,form(
						{method: 'post'}
						,ul(
							li(
								label({'class': 'label'}, "E-mail")
								,inputEmail
							)
						)
						,p(
							{'class': 'paragraph-button'}
							,input({type: 'submit', 'class': 'button', value: 'verstuur'})
						)
						,input({type: 'hidden', name: 'action', value: 'requestpassword'})
					)
				)
			)
		}
		
		$super(pane, 324);
	}
	
	,beforeShow: function(options)
	{
		var errorMessage;
		
		with (options)
		{
			this.setErrorMessage(
				(errorMessage == undefined) 
					? '' 
					: errorMessage);
		}
	}
	
	,afterShow: function(options)
	{
		this.inputEmail.focus();
	}
	
	,setErrorMessage: function(message)
	{
		this.paragraphErrorMessage.update(message);
	}
});

ForgotPasswordDialog.singleton = function()
{
	if (! this.instance)
		this.instance = new ForgotPasswordDialog();
		
	return this.instance;
}


var LoginDialog = Class.create(AbstractDialog, {
	
	initialize: function($super)
	{
		var self = this;
		var pane;
		
		with ($E)
		{
			var buttonClose = a(
				{href: ''}
				,img({src: '/media/gfx/window_close.gif', 'class': 'button-close'})
			);
			
			Event.observe(buttonClose, 'click', function(event) {
				Event.stop(event);
				self.close();
			});

			var paragraphErrorMessage = p({'class':'error-message'});
			this.paragraphErrorMessage = paragraphErrorMessage;
			
			var inputEmail = input({'class': 'text', type: 'text', name: 'email'});
			this.inputEmail = inputEmail;
			
			var inputSo = input({type: 'hidden', name: 'so', value: '0' });
			this.inputSo = inputSo;
			
			var linkForgotPassword = a({href: ''}, "Wachtwoord vergeten?");
			
			Event.observe(linkForgotPassword, 'click', function(event) {
				Event.stop(event);
				ForgotPasswordDialog.singleton().show();
				this.close();
			}.bind(this));
			
			pane = div(
				{'class': 'window-login window-dialog'}
				,buttonClose
				,h1("Inloggen")
				,paragraphErrorMessage
				,fieldset(
					{'class': 'form'}
					,form(
						{method: 'post'}
						,ul(
							li(
								label({'class': 'label'}, "E-mail")
								,inputEmail
							)
							,li(
								label({'class': 'label'}, "Wachtwoord")
								,input({'class': 'text', type: 'password', name: 'wachtwoord'})
							)
						)
						,p(
							{'class': 'paragraph-button'}
							,input({type: 'submit', 'class': 'button', value: 'login'})
						)
						,input({type: 'hidden', name: 'action', value: 'login'})
						,inputSo
					)
					,p(
						{'class': 'paragraph-link'}
						,small(linkForgotPassword)
					)
				)
			)
		}
		
		$super(pane, 324);
	}
	
	,beforeShow: function(options)
	{
		var errorMessage;
		
		with (options)
		{
			(errorMessage)
				? this.setErrorMessage(errorMessage)
				: this.setErrorMessage('');
		}
	}
	
	,afterShow: function()
	{
		this.inputSo.value = document.viewport.getScrollOffsets().top;
		this.inputEmail.focus();
	}
	
	,setErrorMessage: function(message)
	{
		this.paragraphErrorMessage.update(message);
	}
});

LoginDialog.singleton = function()
{
	if (! this.instance)
		this.instance = new LoginDialog();
		
	return this.instance;
}

var Overlay = Class.create({
	
	initialize: function() 
	{
		this.showing = 0;
		
		this.overlay = new Element("div", {'class': 'dialog-overlay'});
		this.overlay.setStyle({ display: 'none'});
		
		$(document.body).insert(this.overlay);
		
		Event.observe(window, 'resize', this.adjustToWindowSize.bind(this));
	}
	
	,show: function()
	{
		if (this.showing++)
			return;
	
		this.adjustToWindowSize();
		
		new Effect.Appear(this.overlay, { duration: 0.5, from: 0.0, to: 0.7 });
	}
	
	,close: function()
	{
		if (this.showing-- == 1)
			new Effect.Fade(this.overlay, { duration: 0.5 });	
	}
	
	,getPageSize: function()
	{ 
		var xScroll, yScroll;
		
		if (window.innerHeight && window.scrollMaxY) {	
			xScroll = window.innerWidth + window.scrollMaxX;
			yScroll = window.innerHeight + window.scrollMaxY;
		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}
		
		var windowWidth, windowHeight;
		
		if (self.innerHeight) {	// all except Explorer
			if(document.documentElement.clientWidth){
				windowWidth = document.documentElement.clientWidth; 
			} else {
				windowWidth = self.innerWidth;
			}
			windowHeight = self.innerHeight;
		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		} else if (document.body) { // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}	
		
		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		} else { 
			pageHeight = yScroll;
		}
	
		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){	
			pageWidth = xScroll;		
		} else {
			pageWidth = windowWidth;
		}

		return {width: pageWidth, height: pageHeight};
	}
	
	,adjustToWindowSize: function()
	{
		var dim = this.getPageSize();
        this.overlay.setStyle({ width: dim.width + 'px', height: dim.height + 'px' });
	}
});

Overlay.singleton = function()
{
	if (! this.instance)
		this.instance = new Overlay();
		
	return this.instance;
}
