(function()
{
	var PAGE_LEAVE_MESSAGE = "You've started writing a prompt, and will lose your progress if you leave.",
		PROMPT_LEAVE_MESSAGE = "Are you sure you want to navigate away from this prompt?\n\nYou've started writing a prompt, and will lose your progress if you leave.\n\nClick OK to continue, or click Cancel to stay on this page."
		LATEST_ANSWERS = '/prompts/%s/recent_answers',
		PREVIEW = '/prompts/%s/preview';
	
	var not_logged_in = true,
		
		right_button = null,
		left_button = null,
		prompt_container = null,
		prompt_loader = null,
		prompt_preview = null,
		prompt_preview_button = null,
		prompt_post_button = null,
		latest_answers = null,
		
		preview_is_open = false,
		can_use_preview = true,
		can_paginate = true,
		is_edit_page = window.location.href.match(/edit$/),
		
		prev_prompt = null,
		next_prompt = null,
		curr_prompt = null,
		curr_prompt_id = null,
		curr_scripts = [],
		curr_styles = [],
		curr_ready_funcs = [],
		curr_loaded_assets = [],
		
		default_title = null,
		title_replacements = null,
		can_replace_title = true,
		prompt_title = null,
		
		is_draft = false,
		validates_against = null,
		extra_fields = [],
		actions_are_disabled = false,
		
		hash_int_id = null;
	
	function registerPrompt(opts)
	{
		if (location.hash != '' && location.hash != opts.curr_prompt)
			return;
		
		can_paginate = false;
		
		prev_prompt = opts.prev_prompt;
		next_prompt = opts.next_prompt;
		curr_prompt = opts.curr_prompt;
		curr_prompt_id = opts.curr_prompt_id;
		
		curr_scripts = opts.require_scripts || [];
		curr_styles = opts.require_styles || [];
		default_title = opts.default_title || '';
		title_replacements = opts.title_replacements || [];
		prompt_title = prompt_container.find('input.prompt_title');
		
		if ($.trim(prompt_title.val()) != '' && prompt_title.val() != generateDefaultTitle())
			can_replace_title = false;
		else
		{
			reloadTitleReplacements();
			updateDefaultTitle();
			
			prompt_title.blur(function()
			{
				var val = $(this).val();
				
				if ($.trim(val) == '' || val == generateDefaultTitle()) can_replace_title = true;
				else can_replace_title = false;
			});
		}
		
		prompt_container.parents('form').attr('action', opts.action);
		prompt_container.find(':input').keyup(checkActionAvailability).change(checkActionAvailability);
		
		is_draft = opts.is_draft || false;
		if (is_draft)
			validates_against = prompt_container.find(':input:not([type=hidden]):visible').serialize();
		
		if (!is_edit_page && location.hash != '')
		{
			location.hash = curr_prompt;
		}
		
		if (opts.require_scripts && opts.require_scripts.length)
			requireScripts(opts.require_scripts);
		
		if (opts.require_styles && opts.require_styles.length)
			requireStyles(opts.require_styles);
		
		if (!opts.require_scripts || opts.require_scripts.length == 0)
		{
			$(window).trigger('paginator:ready');
			
			if (not_logged_in && $('li.card_content').height() < 420)
				$('li.card_content').height(420);
			
			prompt_loader.fadeOut('fast', function()
			{
				prompt_container.fadeIn('fast', function()
				{
					can_paginate = true;
					$(window).trigger('paginator:components');
				});
			});
		}
		
		checkActionAvailability();
		
		right_button.attr('href', next_prompt);
		left_button.attr('href', prev_prompt);
		
		if (not_logged_in)
		{
			prompt_container.parent().find('*').attr('tabindex', '-1');
			if ($('li.card_content').height() < 420)
				$('li.card_content').height(420);
		}
	}
	
	function checkHash()
	{
		if (location.hash == '') return;
		if (location.hash == curr_prompt) return;
		if (!can_paginate) return;
		
		if (getFormValues().length > 0)
		{
			if (confirm(PROMPT_LEAVE_MESSAGE))
			{
				curr_prompt = location.hash;
				unloadPrompt();
				return;
			}
			
			location.hash = curr_prompt;
			
			return;
		}
		
		curr_prompt = location.hash;
		unloadPrompt();
	}
	
	function loadLatestAnswers()
	{
		latest_answers.find('li[class!=header][class!=bottom]:first').fadeOut('fast', function()
		{
			$(this).remove();
			
			$.ajax({
				url: LATEST_ANSWERS.replace('%s', curr_prompt_id),
				dataType: 'html',
				success: function(d)
				{
					$(d).hide().insertAfter(latest_answers.find('li.header')).fadeIn('fast');
					
					if (latest_answers.find('li.none').length > 0)
						latest_answers.find('li.bottom').fadeOut('fast');
					else
						latest_answers.find('li.bottom').fadeIn('fast').find('a').attr('href', '/prompts/%s/answers'.replace('%s', curr_prompt_id));
				}
			})
		});
		
		latest_answers.find('li[class!=header][class!=bottom]:not(:first)').fadeOut('fast', function() { $(this).remove(); } );
	}
	
	function loadPrompt()
	{
		$.get(curr_prompt.substr(1, curr_prompt.length) + '?standalone=true&' + Math.random(), function(d)
		{
			var h = null;
			
			prompt_container.hide();
			
			$(d).appendTo(prompt_container);
			
			h = prompt_container.height() + ($.browser.msie? 80 : 68);
			if (not_logged_in && h < 420)
				h = 420;
			
			prompt_loader.animate({
				height: h
			}, 'easeInOutQuart', function()
			{
				$(window).trigger('paginator:configurable');
				loadLatestAnswers();
			});
		}, 'html');
	}
	
	function unloadPrompt()
	{
		can_paginate = false;
		
		$(window).unbind('paginator:configurable');
		$(window).unbind('paginator:ready');
		
		if (typeof GUnload != 'undefined')
			GUnload();
		
		curr_scripts = [];
		curr_styles = [];
		curr_loaded_assets = [];
		extra_fields = [];
		
		default_title = null;
		title_replacements = null;
		can_replace_title = true;
		prompt_title = null;
		
		actions_are_disabled = false;
		
		var h = prompt_container.height() + $('ul.post_button').height() + ($.browser.msie? 32 : 31)
		if (not_logged_in && h < 420)
			h = 420;
		
		prompt_container.fadeOut('fast', function()
		{
			if (not_logged_in)
				$('li.card_content').css('height', 'auto');
			
			prompt_loader.height(h);
			prompt_loader.fadeIn('fast', function()
			{
				prompt_container.find('*').remove();
				loadPrompt();
			});
		});
	}
	
	function requireScripts(scripts)
	{
		for (var i = 0, l = scripts.length; i<l; i++)
		{
			$.getScript('/javascripts/' + scripts[i] + '.js', requiredAssetLoaded);
		}
	}
	
	function requireStyles(styles)
	{
		for (var i = 0, l = styles.length; i<l; i++)
		{
			$('<link rel="stylesheet" type="text/css" href="/stylesheets/' + styles[i] + '.css" />').appendTo('head');
			curr_loaded_assets.push(true);
			requiredAssetLoaded();
		}
	}
	
	function requiredAssetLoaded()
	{
		curr_loaded_assets.push(true);
		
		if (curr_loaded_assets.length == curr_scripts.length)
		{
			if (not_logged_in && $('li.card_content').height() < 420)
				$('li.card_content').height(420);
				
			prompt_loader.fadeOut('fast', function()
			{
				prompt_container.fadeIn('fast', function()
				{
					can_paginate = true;
					
					$(window).trigger('paginator:ready');
					$(window).trigger('paginator:components');
				});
			});
		}
	}
	
	function buttonClick(e)
	{
		if (!can_paginate)
			e.preventDefault();
	}
	
	function getFormValues(ignore_draft)
	{
		if (is_draft && !ignore_draft)
		{
			if (prompt_container.find(':input:not([type=hidden]):visible').serialize() == validates_against)
				return [];
			else return [true];
		}
		
		var form_values = [];
		$.map(prompt_container.find(':input:not([name*=title]):visible').serializeArray(), function(d)
		{
			if ($.trim(d.value) != '')
			{
				form_values.push(true);
				return true;
			}
			
			return false;
		});
		
		return form_values;
	}
	
	function reloadTitleReplacements()
	{
		if (!can_replace_title)
			return;
		
		$.each(title_replacements, function()
		{
			$(this.toString())
				.unbind('keyup', updateDefaultTitle)
				.unbind('change', updateDefaultTitle)
				.bind('change', updateDefaultTitle)
				.bind('keyup', updateDefaultTitle);
		});
		
		updateDefaultTitle();
	}
	
	function generateDefaultTitle()
	{
		var working_title = default_title,
			val = '';
		
		$.each(title_replacements, function()
		{
			val = ($(this.toString()).val() || '');
			
			working_title = working_title.replace('%s', val).replace('%S', val.substr(0, 1).toUpperCase() + val.substr(1));
		});
		
		return working_title.replace('%s', '');
	}
	
	function updateDefaultTitle()
	{
		if (!can_replace_title)
			return;
		
		prompt_title.val(generateDefaultTitle());
	}
	
	function openPreview(e)
	{
		e.preventDefault();
		
		$(this).blur();
		
		if (getFormValues().length == 0)
			return;
		
		if (preview_is_open)
		{
			closePreview(e);
			return;
		}
		
		if (!can_use_preview)
			return;
		
		preview_is_open = true;
		can_use_preview = false;
		can_paginate = false;
		
		$.ajax({
			url: PREVIEW.replace('%s', curr_prompt_id),
			dataType: 'html',
			data: unescapePreview(prompt_container.find(':input').serialize()),
			success: function(d)
			{
				prompt_preview.find('span.preview_content').html(d);
				prompt_container
					.parents('li.card_content')
						.height(prompt_container.height() + $('ul.post_button').height() + ($.browser.msie? 32 : 32));
				
				left_button.parents('li').animate({ opacity: 0 }, 'slow', function()
				{
					$(this).css('visibility', 'hidden');
				});
				
				right_button.parents('li').animate({ opacity: 0 }, 'slow', function()
				{
					$(this).css('visibility', 'hidden');
				});
				
				prompt_container.fadeOut('slow', function()
				{
					prompt_container
						.parents('li.card_content')
							.animate({
								height: prompt_preview.height() + ($.browser.msie? 9 : 3)
							}, 800, 'easeInOutQuart', function()
							{
								$('ul.post_button li.preview_button a.blue_button').addClass('borderless');
								$('ul.post_button li.preview_button span.preview')
									.fadeOut('fast', function()
									{
										$(this).siblings('span.back').fadeIn('fast');
									});
								
								prompt_preview.fadeIn('slow', function()
								{
									prompt_preview.parents('li.card_content').css('height', 'auto');
									can_use_preview = true;
								});
							});
				});
			}
		});
	}
	
	function closePreview(e)
	{
		e.preventDefault();
		
		if (!can_use_preview)
			return;
		
		preview_is_open = false;
		can_use_preview = false;
		can_paginate = true;
		
		prompt_container.parents('li.card_content').height(
			prompt_preview.height() + ($.browser.msie? 9 : 3)
		);
		
		prompt_preview.fadeOut('slow', function()
		{
			prompt_container
				.parents('li.card_content')
					.animate({
						height: prompt_container.height() + $('ul.post_button').height() + ($.browser.msie? 32 : 16)
					}, 800, 'easeInOutQuart', function()
					{
						left_button.parents('li').css('visibility', 'visible');
						right_button.parents('li').css('visibility', 'visible');
						
						left_button.parents('li').animate({ opacity: 1 }, 'slow');
						right_button.parents('li').animate({ opacity: 1 }, 'slow');
						
						$('ul.post_button li.preview_button a.blue_button').removeClass('borderless');
						$('ul.post_button li.preview_button span.back')
							.fadeOut('fast', function()
							{
								$(this).siblings('span.preview').fadeIn('fast');
							});
						
						prompt_container.fadeIn('slow', function()
						{
							prompt_container.parents('li.card_content').css('height', 'auto');
							can_use_preview = true;
							$(window).trigger('paginator:previewopened');
						});
					});
		});
	}
	
	function checkActionAvailability()
	{
		if (actions_are_disabled)
			return;
		
		if (getFormValues(true).length == 0 || checkExtraFields().length != 0)
		{
			prompt_post_button.css('opacity', .4).find('input').attr('disabled', 'true').css('cursor', 'default');
			prompt_preview_button.css('opacity', .4).find('a').removeAttr('href').css('cursor', 'default');
			return;
		}
		
		prompt_post_button.css('opacity', null).find('input').removeAttr('disabled').css('cursor', 'pointer');
		prompt_preview_button.css('opacity', 1).find('a').attr('href', '#').css('cursor', 'pointer');
	}
	
	function checkExtraFields()
	{
		var field_values = [];
		if (extra_fields && extra_fields.length)
		{
			$.each(extra_fields, function()
			{
				switch(this.attr('type')) {
					case 'checkbox':
						if (this[0].checked != true)
							field_values.push(true);
					break;
					case 'text':
						if ($.trim(this.val()) != '')
							field_values.push(true);
					break;
				}
			});
		}
		
		return field_values;
	}
	
	function addExtraFields(fields)
	{
		$.each(fields, function()
		{
			extra_fields.push($(this).bind('keyup', checkActionAvailability).bind('change', checkActionAvailability));
		});
		
		checkActionAvailability();
	}
	
	function clearExtraFields(fields)
	{
		for (var i = 0, el = extra_fields.length; i<el; i++)
		{
			for (var j = 0, fl = fields.length; j<fl; j++)
			{
				if (extra_fields[i][0] == fields[j][0])
					extra_fields.splice(i, 1);
			}
		}
		
		checkActionAvailability();
	}
	
	function setLoggedIn(is_logged_in)
	{
		not_logged_in = !is_logged_in;
		
		if (not_logged_in)
			$(function()
			{
				$('ul.card_container').mouseup(function(e)
				{
					$('ul.logged_out_cover').show();
					$(e.currentTarget).blur();
				});
			});
	}
	
	function unescapePreview(str)
	{
		return str.replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/\n/g, '<br />').replace(/\r/g, '<br />');
	}
	
	function disableActions()
	{
		actions_are_disabled = true;
	}
	
	function enableActions()
	{
		actions_are_disabled = false;
		checkActionAvailability();
	}
	
	$(function()
	{
		right_button = $('li.right.button a');
		left_button = $('li.left.button a');
		prompt_container = $('span.prompt_container');
		prompt_loader = $('ul.answer_loader');
		prompt_preview = $('ul.answer_preview');
		prompt_preview_button = $('ul.post_button li.preview_button');
		prompt_post_button = $('ul.post_button li.post_button');
		latest_answers = $('ul.latest_responses');
		
		$(window).trigger('paginator:configurable');
		
		right_button.click(buttonClick);
		left_button.click(buttonClick);
		
		right_button.parents('li').hover(function()
		{
			$(this).find('span').toggle();
		}, function()
		{
			$(this).find('span').toggle();
		});
		
		left_button.parents('li').hover(function()
		{
			$(this).find('span').toggle();
		}, function()
		{
			$(this).find('span').toggle();
		});
		
		prompt_preview_button.click(openPreview);
		prompt_preview.find('a.dismiss').click(closePreview);
		
		hash_int_id = setInterval(checkHash, 100);
		checkHash();
		
		window.onbeforeunload = function()
		{
			if (getFormValues().length > 0)
			{
				return PAGE_LEAVE_MESSAGE;
			}
		}
	});
	
	window.Paginator = {
		registerPrompt: registerPrompt,
		getFormValues: getFormValues,
		reloadTitleReplacements: reloadTitleReplacements,
		addExtraFields: addExtraFields,
		clearExtraFields: clearExtraFields,
		setLoggedIn: setLoggedIn,
		disableActions: disableActions,
		enableActions: enableActions
	}
	
})();
