var modalGlobals = {};

function openModal(url, data, modalArgs)
{
	if (data == null)
		data = {};

	if (typeof(data) == "object")
	{
		data["_s"] = randStr(10);
		data = objectToString(data);
	}
	$.get(url, data, function(data){ modalBox(data, modalArgs); }, "html");
}
function objectToString(data, kwargs)
{
	kwargs = kwargs || {};
	var itemDelimiter = kwargs.itemDelimiter || "&";
	var valueDelimiter = kwargs.valueDelimiter || "=";
	var includeEmpty = kwargs.includeEmpty === true; // default to false

	var output = [];
	for (key in data)
		if (includeEmpty || testNullString(data[key]))
			output.push(key + valueDelimiter + testNullString(data[key], ""));

	return output.join(itemDelimiter);
}

function closeModal(modalArgs){ return modalBox(null, modalArgs) }

function isModalOpen() { return $("#nimble_modal").length > 0; }

/**
 * Opens up a modal window with provided content
 * modalArgs can define the following optional params:
 *
 * openCallback: function -- if provided, this function will be executed after the overlay is first brought up
 * closeCallback: function -- if provided, this function will be executed when the overlay is closed
 * overlayOnclick: function -- if provided, this function will be executed when a user clicks on the grayed-out portion of the screen when an overlay is up
 * width: int width -- can manually specify here (can also specify in modal.css)
 * pin: bool -- if true, the modal will not scroll with the window
 **/
function modalBox(content, modalArgs) {
	var modalArgs = modalArgs || {};
	var createModal = $("#nimble_overlay").length == 0;

	var width = modalArgs.width || 350;
	var openCallback = modalArgs.openCallback;
	var closeCallback = modalArgs.closeCallback;
	var overlayOnclick = modalArgs.overlayOnclick || function(){ modalBox(); }
	var pin = modalArgs.pin !== false; // default to pinning the modal

	if (!content && modalGlobals.restoreContent)
	{
		restoreModalState();
		return;
	}

	if(!content) {
		$('#nimble_modal').remove();
		$('#nimble_overlay').fadeOut(function(){$(this).remove(); if (typeof(closeCallback) == "function"){closeCallback();} });

		return false;
	}

	if (createModal) {
		//try{if(IE6){$('body').find('select:visible').addClass('unhideThis').visibility('hidden');}}catch(err){};
		//$('embed:visible, object:visible').addClass('unhideThis').css('visibility', 'hidden');
		$('body').append('<div id="nimble_overlay"></div>');
		$('#nimble_overlay').css({
			height : $(document).height()
		}).fadeTo(500, 0.75).click(overlayOnclick);
		$('body').append('<div id="nimble_modal"></div>');
		$('#nimble_modal').css({
			width : width,
			top : $(document).scrollTop() + 50,
			marginLeft : -(Math.ceil((width)/2))
		}).append(content);
	}
	else // A modal is already open, reset its bound functions
	{
		$(document).unbind('scroll');
		$('#nimble_overlay').unbind("click").click(overlayOnclick);
		$("#nimble_modal").html(content);
	}

	width = modalArgs.width || $("#nimble_modal :first").width();
	$('#nimble_modal').css({width: width, marginLeft: -(Math.ceil(width / 2))});
	$('#nimble_modal input:eq(0)').focus();

	if (typeof(openCallback) == "function")
		openCallback();

	if (pin)
	{
		$(document).unbind('scroll');

		scrollTo(0, 0);
		$('#nimble_modal').animate({
			top: 50
		}, 0);
	}
	else
	{
		$(document).bind('scroll', function(){
			$('#nimble_modal').queue([]); // scroll fires many times on a scroll, we don't want the animation queue to back up, clear it.
			$('#nimble_modal').animate({
				top: $(document).scrollTop() + 50
			}, 300);
		});
	}
};

function saveModalState(saveFormState)
{
	saveFormState = (saveFormState === true);

	var isFromOverlay = isModalOpen();
	if (!isFromOverlay)
		return;

	modalGlobals.restoreContent = $("#nimble_modal").html();

	if (saveFormState)
	{
		modalGlobals.restoreForm = {};
		var tmpInputs = $("#nimble_modal input, "+ MODAL_ID +" select");

		for (var i = 0; i < tmpInputs.length; i ++)
		{
			var curInput = tmpInputs[i];

			if (curInput.type == "checkbox")
				modalGlobals.restoreForm[curInput.id] = curInput.checked;
			else
				modalGlobals.restoreForm[curInput.id] = curInput.value;
		}
	}
	else
		modalGlobals.restoreForm = {};
}

function restoreModalState()
{
	if (modalGlobals.restoreContent)
		modalBox(modalGlobals.restoreContent)
	else // No modal to restore. Close the overlay (there might be a form underneath that instigated the overlay)
		closeModal();

	if (modalGlobals.restoreForm)
	{
		for (var key in modalGlobals.restoreForm)
		{
			try {
				if (/password/i.test(key)) // don't restore password fields
					continue;

				if (key == "credit_package")
					$("#nimble_modal #credit_"+ modalGlobals.restoreForm[key]).trigger("click");
				else
				{
					var curInput = $("#nimble_modal #"+ key)[0];

					if (curInput.type == "checkbox")
						curInput.checked = modalGlobals.restoreForm[key];
					else
						curInput.value = modalGlobals.restoreForm[key];
				}
			} catch(e) {}
		}
	}

	modalGlobals.restoreContent = null;
}
function randStr(length)
{

	var src = "abcdefghijklmnopqrstuvwxyz0123456789";
	src = src.split("");
	
	var randomized = [];
	for (var i = 0; i < length; i ++)
		randomized.push(src[Math.floor(Math.random() * src.length)]);
	return randomized.join("");
}
function testNullString(value, returnIfNull)
{
	value = String(((value || value == 0) ? value : ""));
	returnIfNull = ((typeof(returnIfNull) != "undefined") ? returnIfNull : null);
	return ((value && value != "undefined") ? value : returnIfNull);
}

