/*
 * jQuery Impromptu
 * By: Trent Richardson [http://trentrichardson.com]
 * Version 3.0
 * Last Modified: 2/15/2010
 * 
 * Copyright 2010 Trent Richardson
 * Dual licensed under the MIT and GPL licenses.
 * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
 * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
 * 
 */
(function($) {
	$.prompt = function(message, options) {
		options = $.extend( {}, $.prompt.defaults, options);
		$.prompt.currentPrefix = options.prefix;
		var ie6 = ($.browser.msie && $.browser.version < 7);
		var $body = $(document.body);
		var $window = $(window);
		options.classes = $.trim(options.classes);
		if (options.classes != '')
			options.classes = ' ' + options.classes;
		var msgbox = '<div class="' + options.prefix + 'box' + options.classes + '" id="' + options.prefix + 'box">';
		if (options.useiframe && (($('object, applet').length > 0) || ie6)) {
			msgbox += '<iframe src="javascript:false;" style="display:block;position:absolute;z-index:-1;" class="' + options.prefix + 'fade" id="' + options.prefix + 'fade"></iframe>';
		} else {
			if (ie6) {
				$('select').css('visibility', 'hidden');
			}
			msgbox += '<div class="' + options.prefix + 'fade" id="' + options.prefix + 'fade"></div>';
		}
		msgbox += '<div class="' + options.prefix + '" id="' + options.prefix + '"><div class="' + options.prefix + 'container"><div class="';
		msgbox += options.prefix + 'close">X</div><div id="' + options.prefix + 'states"></div>';
		msgbox += '</div></div></div>';
		var $jqib = $(msgbox).appendTo($body);
		var $jqi = $jqib.children('#' + options.prefix);
		var $jqif = $jqib.children('#' + options.prefix + 'fade');
		if (message.constructor == String) {
			message = {
				state0 : {
					html : message,
					buttons : options.buttons,
					focus : options.focus,
					submit : options.submit
				}
			};
		}
		var states = "";
		$
			.each(
				message,
				function(statename, stateobj) {
					stateobj = $.extend( {}, $.prompt.defaults.state, stateobj);
					message[statename] = stateobj;
					states += '<div id="' + options.prefix + '_state_' + statename + '" class="' + options.prefix + '_state" style="display:none;"><div class="' + options.prefix + 'message">' + stateobj.html + '</div><div class="' + options.prefix + 'buttons">';
					$
						.each(
							stateobj.buttons,
							function(k, v) {
								states += '<button name="' + options.prefix + '_' + statename + '_button' + k + '" id="' + options.prefix + '_' + statename + '_button' + k + '" value="' + v + '">' + k + '</button>';
							});
					states += '</div></div>';
				});
		$jqi.find('#' + options.prefix + 'states').html(states).children(
			'.' + options.prefix + '_state:first').css('display', 'block');
		$jqi.find('.' + options.prefix + 'buttons:empty')
			.css('display', 'none');
		$
			.each(
				message,
				function(statename, stateobj) {
					var $state = $jqi
						.find('#' + options.prefix + '_state_' + statename);
					$state
						.children('.' + options.prefix + 'buttons')
						.children('button')
						.click(
							function() {
								var msg = $state
									.children('.' + options.prefix + 'message');
								var clicked = stateobj.buttons[$(this).text()];
								var forminputs = {};
								$
									.each(
										$jqi
											.find(
												'#' + options.prefix + 'states :input')
											.serializeArray(),
										function(i, obj) {
											if (forminputs[obj.name] === undefined) {
												forminputs[obj.name] = obj.value;
											} else if (typeof forminputs[obj.name] == Array || typeof forminputs[obj.name] == 'object') {
												forminputs[obj.name]
													.push(obj.value);
											} else {
												forminputs[obj.name] = [
													forminputs[obj.name],
													obj.value ];
											}
										});
								var close = stateobj.submit(clicked, msg,
									forminputs);
								if (close === undefined || close) {
									removePrompt(true, clicked, msg, forminputs);
								}
							});
					$state
						.find(
							'.' + options.prefix + 'buttons button:eq(' + stateobj.focus + ')')
						.addClass(options.prefix + 'defaultbutton');
				});
		var ie6scroll = function() {
			$jqib.css( {
				top : $window.scrollTop()
			});
		};
		var fadeClicked = function() {
			if (options.persistent) {
				var i = 0;
				$jqib.addClass(options.prefix + 'warning');
				var intervalid = setInterval(function() {
					$jqib.toggleClass(options.prefix + 'warning');
					if (i++ > 1) {
						clearInterval(intervalid);
						$jqib.removeClass(options.prefix + 'warning');
					}
				}, 100);
			} else {
				removePrompt();
			}
		};
		var keyPressEventHandler = function(e) {
			var key = (window.event) ? event.keyCode : e.keyCode;
			if (key == 27) {
				fadeClicked();
			}
			if (key == 9) {
				var $inputels = $(':input:enabled:visible', $jqib);
				var fwd = !e.shiftKey && e.target == $inputels[$inputels.length - 1];
				var back = e.shiftKey && e.target == $inputels[0];
				if (fwd || back) {
					setTimeout(
						function() {
							if (!$inputels)
								return;
							var el = $inputels[back === true ? $inputels.length - 1 : 0];
							if (el)
								el.focus();
						}, 10);
					return false;
				}
			}
		};
		var positionPrompt = function() {
			$jqib.css( {
				position : (ie6) ? "absolute" : "fixed",
				height : $window.height(),
				width : "100%",
				top : (ie6) ? $window.scrollTop() : 0,
				left : 0,
				right : 0,
				bottom : 0
			});
			$jqif.css( {
				position : "absolute",
				height : $window.height(),
				width : "100%",
				top : 0,
				left : 0,
				right : 0,
				bottom : 0
			});
			$jqi.css( {
				position : "absolute",
				top : options.top,
				left : "50%",
				marginLeft : (($jqi.outerWidth() / 2) * -1)
			});
		};
		var stylePrompt = function() {
			$jqif.css( {
				zIndex : options.zIndex,
				display : "none",
				opacity : options.opacity
			});
			$jqi.css( {
				zIndex : options.zIndex + 1,
				display : "none"
			});
			$jqib.css( {
				zIndex : options.zIndex
			});
		};
		var removePrompt = function(callCallback, clicked, msg, formvals) {
			$jqi.remove();
			if (ie6) {
				$body.unbind('scroll', ie6scroll);
			}
			$window.unbind('resize', positionPrompt);
			$jqif.fadeOut(options.overlayspeed, function() {
				$jqif.unbind('click', fadeClicked);
				$jqif.remove();
				if (callCallback) {
					options.callback(clicked, msg, formvals);
				}
				$jqib.unbind('keypress', keyPressEventHandler);
				$jqib.remove();
				if (ie6 && !options.useiframe) {
					$('select').css('visibility', 'visible');
				}
			});
		};
		positionPrompt();
		stylePrompt();
		if (ie6) {
			$window.scroll(ie6scroll);
		}
		$jqif.click(fadeClicked);
		$window.resize(positionPrompt);
		$jqib.bind("keydown keypress", keyPressEventHandler);
		$jqi.find('.' + options.prefix + 'close').click(removePrompt);
		$jqif.fadeIn(options.overlayspeed);
		$jqi[options.show](options.promptspeed, options.loaded);
		$jqi
			.find(
				'#' + options.prefix + 'states .' + options.prefix + '_state:first .' + options.prefix + 'defaultbutton')
			.focus();
		if (options.timeout > 0)
			setTimeout($.prompt.close, options.timeout);
		return $jqib;
	};
	$.prompt.defaults = {
		prefix : 'jqi',
		classes : '',
		buttons : {
			Ok : true
		},
		loaded : function() {
		},
		submit : function() {
			return true;
		},
		callback : function() {
		},
		opacity : 0.6,
		zIndex : 999,
		overlayspeed : 'slow',
		promptspeed : 'fast',
		show : 'fadeIn',
		focus : 0,
		useiframe : false,
		top : "15%",
		persistent : true,
		timeout : 0,
		state : {
			html : '',
			buttons : {
				Ok : true
			},
			focus : 0,
			submit : function() {
				return true;
			}
		}
	};
	$.prompt.currentPrefix = $.prompt.defaults.prefix;
	$.prompt.setDefaults = function(o) {
		$.prompt.defaults = $.extend( {}, $.prompt.defaults, o);
	};
	$.prompt.setStateDefaults = function(o) {
		$.prompt.defaults.state = $.extend( {}, $.prompt.defaults.state, o);
	};
	$.prompt.getStateContent = function(state) {
		return $('#' + $.prompt.currentPrefix + '_state_' + state);
	};
	$.prompt.getCurrentState = function() {
		return $('.' + $.prompt.currentPrefix + '_state:visible');
	};
	$.prompt.getCurrentStateName = function() {
		var stateid = $.prompt.getCurrentState().attr('id');
		return stateid.replace($.prompt.currentPrefix + '_state_', '');
	};
	$.prompt.goToState = function(state) {
		$('.' + $.prompt.currentPrefix + '_state').slideUp('slow');
		$('#' + $.prompt.currentPrefix + '_state_' + state).slideDown(
			'slow',
			function() {
				$(this).find('.' + $.prompt.currentPrefix + 'defaultbutton')
					.focus();
			});
	};
	$.prompt.nextState = function() {
		var $next = $('.' + $.prompt.currentPrefix + '_state:visible').next();
		$('.' + $.prompt.currentPrefix + '_state').slideUp('slow');
		$next.slideDown('slow', function() {
			$next.find('.' + $.prompt.currentPrefix + 'defaultbutton').focus();
		});
	};
	$.prompt.prevState = function() {
		var $next = $('.' + $.prompt.currentPrefix + '_state:visible').prev();
		$('.' + $.prompt.currentPrefix + '_state').slideUp('slow');
		$next.slideDown('slow', function() {
			$next.find('.' + $.prompt.currentPrefix + 'defaultbutton').focus();
		});
	};
	$.prompt.close = function() {
		$('#' + $.prompt.currentPrefix + 'box').fadeOut('fast', function() {
			$(this).remove();
		});
	};
	$.fn.prompt = function(options) {
		if (options == undefined)
			options = {};
		if (options.withDataAndEvents == undefined)
			options.withDataAndEvents = false;
		$.prompt($(this).clone(withDataAndEvents).html(), options);
	}
})(jQuery);