(function() {
	function removeProtocol(href) {
		return href.replace(/^([^:\/]+):\/\/([^:\/]+)((:[0-9]+))?/, "");
	}
	function extractBase(href) {
		href = removeProtocol(href);
		if (href.charAt(href.length - 1) == "/") return href;
		//alert("stripping");
		var slash = href.lastIndexOf('/');
		return href.substring(0, slash + 1);
	}
	var jBody;
	var dialogStack = [];
	var overlay = jQuery("<div class='modalDialogOverlay'></div>");
	var base = extractBase(document.URL);
	var overlayZIndex;
	var fixedFlash = [];
	function makeAbsoluteUrl(href) {
		href = href.replace(/^([^:\/]+):\/\/([^:\/]+)((:[0-9]+))?/, "");
		if (href.charAt(0) != '/') {
			var localBase;
			if (dialogStack.length) {
				localBase = dialogStack[dialogStack.length - 1].base;
			} else {
				localBase = base;
			}
			href = localBase + href;
		}
		return href;
	}

	function initDialogSystem() {
		jBody = jQuery("body");
		overlay.appendTo("body");
		if (jQuery.browser.msie) {
			jQuery("html, body").css("height", "100%");
			var ieOverlay = overlay.css("position", "absolute")[0];
			for (var p in ["Top", "Left"]) {
				ieOverlay.style.setExpression(p.toLowerCase(),"(_=(document.documentElement.scroll"+p+" || document.body.scroll"+p+"))+'px'");
			}
		}
	}
	function popDialog() {
		var item = dialogStack.pop();
		if (item.onClose) item.onClose();
		var widgetName = item.dialog.attr("wsWidgetName");
		if (widgetName) OpenAjax.hub.publish("widget." + widgetName + ".close");
		item.dialog.remove();
		for (var handle in item.handles) {
			OpenAjax.hub.unsubscribe(handle);
		}
		if (dialogStack.length) {
			overlay.css("z-index", dialogStack.length + overlayZIndex - 1);
		} else {
			for (var i = 0; i < fixedFlash.length; i++) {
				fixedFlash[i]();
			}
			fixedFlash = [];
			overlay.hide();
		}
	}
	function pushDialog(dialog, href, handles, onClose) {
		if (!dialogStack.length) {
			overlayZIndex = parseInt(overlay.css("z-index"));
			if (false) jQuery("embed[@type='application/x-shockwave-flash']").each(function() {
				var thiz = this;
				var wmode = this.getAttribute("wmode");
				if (wmode == "transparent") {
					return;
				} else if (wmode == 'opaque') {
					return;
				} else if (wmode) {
					fixedFlash[fixedFlash.length] = function() {
						thiz.setAttribute("wmode", wmode);
					};
				} else {
					fixedFlash[fixedFlash.length] = function() {
						thiz.setAttribute("wmode", "false");
					};
				}
				this.setAttribute("wmode", "opaque");
			});
			overlay.show();
		}
		var zIndex =  dialogStack.length + overlayZIndex;
		dialog.css("z-index", zIndex + 1);
		overlay.css("z-index", zIndex + 1);
		dialogStack.push({dialog: dialog, base: extractBase(href), handles: handles, onClose: onClose});
		setTimeout(function() { overlay.css("z-index", zIndex); }, 1);
	}
	function popupClickHandler() {
		var href = this.getAttribute("href");
		if (href[0] != "/") href = base + href;
		var widgetName = this.getAttribute("wsWidgetName");
		var title = this.getAttribute("wsTitle");
		var jThis = jQuery(this);

		openDialog(jThis, href, widgetName, title);
		return false;
	}
	var startDrag, stopDrag;
	(function() {
		var dragItem, dragCoords, dragCount;
		function placeItem(e) {
			var coords = webslinger.fixMouseEvent(e);
			var xChange = coords[0] - dragCoords[0];
			var yChange = coords[1] - dragCoords[1];
			var item = dragItem;
			item.css("top", parseInt(item.css("top")) + yChange);
			item.css("left", parseInt(item.css("left")) + xChange);
			item.attr("_top", item.css("top"));
			item.attr("_left", item.css("left"));
			return coords;
		}
		var mouseMove = function(e) {
			dragCount++;
			if (dragCount != 10) return;
			dragCount = 0;
			dragCoords = placeItem(e);
		};
		var mouseUp = function(e) {
			placeItem(e);
			stopDrag();
		};
		var origStartDrag, origStopDrag;
		origStartDrag = function(item, e) {
			dragCount = 0;
			dragItem = item;
			dragCoords = webslinger.fixMouseEvent(e);
			stopDrag = origStopDrag;
			jQuery(document).mousemove(mouseMove).mouseup(mouseUp);
		};
		origStopDrag = function() {
			jQuery(document).unbind("mousemove", mouseMove);
			jQuery(document).unbind("mouseup", mouseUp);
			dragItem = dragCoords = dragCoords = null;
			stopDrag = function() {};
			startDrag = origStartDrag;
		};

		startDrag = origStartDrag;
		stopDrag = function() { };
	})();
	jQuery.fn.openDialog = function(href, widgetName, title, context, onClose) {
		//alert("openDialog(" + jThis + ", " + href + ", " + widgetName + ", " + title + ")");
		var jThis = this;
		var modalDialog;
		var modalWrapper;
		var eventData;
		if (!context) context = {};
		var latch = webslinger.Latch(
			2,
			function() {
				jThis.after(modalWrapper);
				modalDialog = new jQuery(jThis.get(0).nextSibling);
				if (widgetName) modalDialog.attr("wsWidgetName", widgetName);
				modalDialog = modalDialog.remove().appendTo("body").show();
				placePopup();
				var handles = [];
				if (widgetName) {
					handles[0] = OpenAjax.hub.subscribe(
						"widget." + widgetName + ".refresh",
						function(name, context) {
							OpenAjax.hub.publish("widget." + widgetName + ".clear");
							loadPopup(context);
						}
					);
					handles[1] = OpenAjax.hub.subscribe(
						"widget." + widgetName + ".resize",
						function(name, context) {
							placePopup();
							OpenAjax.hub.publish("widget." + widgetName + ".resized");
						}
					);
				}
				modalDialog.find(".modalBar").mousedown(function(e) {
					startDrag(modalDialog, e);
				}).css("cursor", "pointer");
				if (title) modalDialog.find(".modalTitle").empty().append(title);
				modalDialog.find("[@modalButton]").click(
					function() {
						switch (this.getAttribute("modalButton")) {
							case "close":
								popDialog();
								break;
						}
						return false;
					}
				);
				pushDialog(modalDialog, href, handles, onClose);
				fillPopup(eventData);
			}
		);
		webslinger.event(
			"/Modal",
			function (data) {
				modalWrapper = data;
				latch();
			}
		);
		webslinger.event(
			href,
			context,
			function(data) {
				eventData = data;
				latch();
			}
		);
		function loadPopup(context) {
			webslinger.event(
				href,
				function(data) {
					fillPopup(data, context);
				}
			);
		}
		function placePopup() {
			if (modalDialog.attr("_top") == null) {
				modalDialog.css("top", (jBody.height() - modalDialog.height()) / 2);
				modalDialog.css("left", (jBody.width() - modalDialog.width()) / 2);
			}
			modalDialog.WidgetSendResizeEvent();
		}
		function fillPopup(data, context) {
			var content = modalDialog.find(".modalContent");
			content.empty().append(data);
			placePopup();
			content.applyMutators();
			placePopup();
			//alert("width(" + modalDialog.width() + ") height(" + modalDialog.height() + ")");

			var setupForm = function(context) {
				var form = content.find("form");
				form.ajaxForm({
					type:		"POST",
					dataType:	"json",
					success:	function(result) {
						if (result.hub) {
							for (var i = 0; i < result.hub.length; i++) {
								var item = result.hub[i];
								OpenAjax.hub.publish(item.topic, item.data);
							}
						}
						if (result.isError) {
							if (result.page) {
								if (widgetName) OpenAjax.hub.publish("widget." + widgetName + ".clear");
								fillPopup(result.page);
							}
						} else {
							popDialog();
						}
					}
				}).attr("action", href).append("<input type='hidden' name='isJson' value='true' />");
				if (context) for (var name in context) {
					var inputElement = form.get(0)[name];
					var value = context[name];
					if (inputElement.nodeName == "select") {
						var options = inputElement.options;
						for (var i = 0; i < options.length; i++) {
							if (options[i].value == value) {
								options[i].selected = true;
								break;
							}
						}
					} else {
						inputElement.value = value;
					}
				}
			};
			setupForm(context);
			if (widgetName) OpenAjax.hub.publish("widget." + widgetName + ".fill");
		}
	};

	jQuery.fn.dialog = function() {
		this.click(function() {
			var href = makeAbsoluteUrl(this.getAttribute("href"));
			var widgetName = this.getAttribute("wsWidgetName");
			var title = this.getAttribute("wsTitle");

			jQuery(this).openDialog(href, widgetName, title);
			return false;
		});
	};
	jQuery(initDialogSystem);
	jQuery.addMutator(function(ctx) {
		jQuery("*[@wsDialog='true']", ctx).dialog();
	});
})();

function openDialog(which) {
	jQuery(
		function() {
			jQuery("*[@wsDialog='true']").each(
				function() {
					var slash = href.indexOf("/");
					if (href.substring(slash + 1) == which) jThis.click();
				}
			);
		}
	);
}
