NetR = typeof NetR === 'undefined' ? {} : NetR;

NetR.DialogHandler = {
	dialogs: [],
	addDialog: function (dialog) {
		if (!this.container) {
			// Create nodes if not yet created
			this.create();
		}
		this.dialogs.push(dialog);
		return dialog;
	},
	create: function () {
		var t = this;
		this.container = $('<div id="dialogs">').appendTo($('body'));

		this.container.click(function (e) {
			if (e.target === t.container[0]) {
				$.each(t.dialogs, function () {
					this.hide();
				});
			}
		});

		// Create and hide spinner
		this.spinner = $('<img src="/i/spinner.gif" id="dialog-spinner" />').appendTo(this.container).hide();
		this.positionSpinner();

		this.resize();
		this.hideContainer();
		$(window).resize(function () {
			if (!t.disableResize) {
				t.resize();
				t.positionSpinner();
			}
		});
	},
	show: function () {
		var t = this;
		this.container.css({
			visibility: '',
			display: 'none',
			overflow: ''
		});
		this.disableResize = false;
		this.resize();
		this.container.fadeIn('normal', function () {
			t.resize();
		});
	},
	hide: function (callback) {
		var t = this;
		this.container.fadeOut('normal', function () {
			t.hideContainer();
			t.hideSpinner();
			t.disableResize = true;
			callback();
		});
	},
	hideContainer: function () {
		this.container.css({
			display: 'block',
			height: 0,
			overflow: 'hidden'
		});
	},
	resize: function () {
		this.container.css('height', $(document).height());
	},
	showSpinner: function () {
		this.spinner.show();
	},
	hideSpinner: function () {
		this.spinner.hide();
	},
	positionSpinner: function () {
		this.spinner.css('top', $(window).height() / 2);
	}
	
};


NetR.Dialog = function (options) {
	var t = this;
	this.options = $.extend({}, NetR.Dialog.defaultOptions, options || {});
	$.each(this.options.callbacks, function (eventName, func) {
		t.addCallback(eventName, func);
	});
};
NetR.Dialog.defaultOptions = {
	callbacks: {},
	template: '<div class="dialog"><a href="#" class="dialog-close"><span>Stäng</span></a><div class="dialog-tl"></div><div class="dialog-br"></div><div class="dialog-tr"><div class="dialog-bl"><div class="dialog-content"></div></div></div></div>',
	extraContainerClass: '',
	offsetTop: 30,
	closeOnEsc: true
};
NetR.Dialog.prototype = {
	contentCache: {},
	callbacks: {},
	addCallback: function (eventName, func) {
		if (typeof func == 'function') {
			if (!this.callbacks[eventName]) {
				this.callbacks[eventName] = [];
			}
			this.callbacks[eventName].push(func);
		}
	},
	doCallback: function (eventName) {
		var t = this;
		if (this.callbacks[eventName]) {
			$.each(this.callbacks[eventName], function () {
				this.apply(t);
			});
		}
	},
	show: function () {
		var t = this;
		this.doCallback('onBeforeShow');

		// Make sure nodes are created
		if (!this.container) {
			this.create();
		}
		this.container.removeClass('hidden');

		if (this.options.closeOnEsc) {
			this.observeEscPress();
		}

		this.container.fadeIn('fast', function () {
			t.position();
			NetR.DialogHandler.show();
			t.doCallback('onAfterShow');
		});
	},
	observeEscPress: function () {
		var t = this;
		var keyObserver = function (e) {
			if (e.keyCode == 27) {
				t.hide();
				$(document).unbind('keypress', keyObserver);
			}
		};
		$(document).keypress(keyObserver);
	},
	hide: function () {
		var t = this;
		this.doCallback('onBeforeHide');
		NetR.DialogHandler.hide(function () {
			t.container.addClass('hidden');
			t.doCallback('onAfterHide');
		});
	},
	create: function () {
		var t = this;
		var buttonTop;
		var buttonLeft;
		var buttonHeight;
		var dialogHeight;

		this.doCallback('onBeforeCreate');

		// Parse template string and make nodes
		this.container = $(this.options.template);
		this.container.addClass(this.options.extraContainerClass);

		// Get main heading
		this.mainHeading = this.container.find('.dialog-heading');

		// Get content
		this.content = this.container.find('.dialog-content');

		// Get close button and set event observer
		this.closeButton = this.container.find('.dialog-close');
		this.closeButton.click(function (e) {
			e.preventDefault();
			t.hide();
		});

		this.setButtonPosition = function () {
			if (typeof buttonTop == 'undefined') {
				buttonTop = t.closeButton.offset().top;
				buttonLeft = t.closeButton.offset().left;
				buttonHeight = t.closeButton.outerHeight();
				dialogHeight = t.content.outerHeight();
			}
			var scrollTop = $(document).scrollTop();
			if (scrollTop > buttonTop) {
				if (scrollTop < buttonTop + dialogHeight - buttonHeight) {
					// Dock button to top of viewport
					t.closeButton.css({
						position: 'fixed',
						top: 0,
						right: 'auto',
						bottom: 'auto',
						left: buttonLeft
					});
				} else {
					t.closeButton.css({
						position: 'absolute',
						top: 'auto',
						right: 'auto',
						bottom: 0,
						left: '100%'
					});
				}
			} else {
				t.closeButton.css({
					position: '',
					top: '',
					right: '',
					bottom: '',
					left: ''
				});
			}
		};

		$(window).scroll(this.setButtonPosition);

		// Append container node to dialogs container
		this.container.appendTo(NetR.DialogHandler.container);

		// Set any cached content
		this.setCachedContent();

		this.doCallback('onAfterCreate');
	},
	setContent: function (content) {
		if (this.container) {
			this.doCallback('onBeforeSetContent');
			this.content.html(content);
			this.position();
			this.doCallback('onAfterSetContent');
		} else {
			// Nodes are not yet created, cache content for later use
			this.contentCache.setContent = content;
		}
	},
	setMainHeading: function (content) {
		if (this.container) {
			this.mainHeading.html(content);
		} else {
			// Nodes are not yet created, cache content for later use
			this.contentCache.setMainHeading = content;
		}
	},
	setCachedContent: function () {
		var t = this;
		$.each(this.contentCache, function (contentFuncName, value) {
			// Set content on correct node
			t[contentFuncName](value);
			// Clear cache for node
			delete t.contentCache[contentFuncName];
		});
	},
	position: function () {
		var width;
		var top;
		var oldDisplay = this.container.css('display');

		this.container.css({
			display: 'none',
			visibility: 'hidden'
		});

		width = this.container.width();

		// Calculate top of dialog
		top = $(window).scrollTop() + this.options.offsetTop;

		this.container.css({
			display: oldDisplay,
			visibility: 'visible',
			top: top,
			left: ($(window).width() / 2) - (width / 2)
		});

		this.setButtonPosition();
	}
};


NetR.DialogHandler.Util = {
	createBasicAjaxDialog: function (target, options) {
		options = $.extend({
			hijackForms: true
		}, options || {});
		// Get form selector
		var selector = ('#' + target.hash).replace('##', '#');

		if (!target.dialog) {
			// Create dialog instance
			var dialog = NetR.DialogHandler.addDialog(new NetR.Dialog({
				callbacks: {
					onAfterSetContent: function () {
						// Find form
						var form = dialog.content.find('form');
						// Make pretty form
						SolnaStad.FormFixer.init(form);
						// Find ReadSpeaker link
						dialog.content.find(".listen a").each(function() {
							var rs = new SolnaStad.ReadSpeakerPlayer(this);
						});
						// Hijack submit event unless it contains file uploads
						if (options.hijackForms && form.attr('enctype') != 'multipart/form-data') {
							// Observe submit event
							form.submit(function (e) {
								e.preventDefault();
								// Post/get with ajax
								$[form.attr('method') || 'post'](form.attr('action'), form.serialize(), function (data) {
									var content = selector == '#' ? data : $(selector, data);
									if (content.length) {
										// Set new dialog content
										target.dialog.setContent(content);
									} else {
										target.dialog.setContent('<p>Ett fel har tyvärr uppstått. Var vänlig försök igen.</p>');
									}
								});
							});
						}
					},
					onAfterHide: function () {
						// Remove any ReadSpeaker players so they don't keep playing in the background
						dialog.content.find('.listen object, .listen embed').remove();
						dialog.content.find(".listen a").show();
					}
				}
			}));

			target.dialog = dialog;
		}

		NetR.DialogHandler.show();
		// Show spinner animation
		NetR.DialogHandler.showSpinner();

		if (target.href.replace(/#.*$/, '') != document.URL) {
			// IE seems to escape the hash part and send it along to the server.
			// This might cause an error, so we have to take the hash part away before requesting		
			
			var errormsg = '<h2>Felmeddelande</h2><p>Ett fel har tyvärr uppstått. Var vänlig försök igen.</p>';
			
			$.ajax({
				url: target.href.stripHash(),
				success: function (data) {
					var content = selector == '#' ? data : $(selector, data);

					if (content.length) {
						target.dialog.setContent(content);
						var chooseQuestionsForm = content.find('.choose-questions');

						if (chooseQuestionsForm.length) {
							var maximumQuestions = chooseQuestionsForm.attr('class').match(/max-(\d+)/);
							maximumQuestions = maximumQuestions ? maximumQuestions[1] : 5;
							new SolnaStad.SelectableQuestions(chooseQuestionsForm, maximumQuestions);
						}
					}
					else {
						target.dialog.setContent(errormsg);
					}
					
					NetR.DialogHandler.hideSpinner();
					target.dialog.show();
				},
				timeout: 10000,
				error: function() {
					target.dialog.setContent(errormsg);
					NetR.DialogHandler.hideSpinner();
					target.dialog.show();
				}
			});
		} else {
			target.dialog.setContent($(selector));
			NetR.DialogHandler.hideSpinner();
			target.dialog.show();
		}

		return target.dialog;
	}
};

$.fn.openAsDialog = function (options) {
	this.each(function () {
		var dialog;
		$(this).click(function (e) {
			e.preventDefault();
			if (!dialog) {
				dialog = NetR.DialogHandler.Util.createBasicAjaxDialog(this, options);
			} else {
				dialog.show();
			}
		});
	});
};
