var PCWN = {

	/*
	 * All params are passed to $.ajax()
	 *
	 * @param url
	 * @param data
	 * @param success (optional)
	 * @param noBusy (optional)
	 */
	postAjax: function(attrs) {
		if (!attrs.noBusy)
			this.showBusy();
		var originalSuccess = attrs.success;
		attrs.type = "POST";
		attrs.dataType = "json";
		attrs.success = function (data, textStatus) {
			if (data.error) {
				var content = "";
				for (var i in data.errors) {
					content += "<li>" + data.errors[i] + "</li>";
				}
				PCWN.showErrorDialog("<div class=\"formErrors\"><ul>" + content + "</ul></div>");
			} else if (originalSuccess != null) {
				originalSuccess(data, textStatus);
			}
			PCWN.hideBusy();
		}
		attrs.error = function (XMLHttpRequest, textStatus, errorThrown) {
			PCWN.hideBusy();
			PCWN.showErrorDialog(PCWN.getMessage("ajax.error"));
		}
		$.ajax(attrs);
	},

	showErrorDialog: function(content, customTitle) {
		$("#dialog").html(content);
		$("#dialog").dialog({
			bgiframe:true,
			modal:true,
			dialogClass: "error",
			draggable: false,
			resizable: false,
			title: customTitle || PCWN.getMessage("errorDialog.defaultTitle"),
			close: function (event, ui) {
				$("#dialog").dialog('destroy')
			},
			open: function(event, ui) {
				var o = {};
				o[PCWN.getMessage("errorDialog.OK")] = function() { $(this).dialog("close"); }
				$("#dialog").dialog("option", "buttons", o);
			}
		});
	},

	showBusy: function() {
		var pageSizes = qm_getPageSize();
		var pageScrolls = qm_getPageScroll();
		$("#pc-busyOverlay")
			.css({width:pageSizes[0],height:pageSizes[1]})
			.show();
		$("#pc-busyContent")
			.css({
				left:Math.ceil((pageSizes[2] - $("#pc-busyContent").width()) / 2 + pageScrolls[0]),
				top:Math.ceil((pageSizes[3] - $("#pc-busyContent").height()) / 3 + pageScrolls[1])
				})
			.show();
	},

	hideBusy: function() {
		$("#pc-busyContent").hide();
		$("#pc-busyOverlay").hide();
	},

	// Unfortunately JavaScript does not provide any means of TZ or DST resolution whatsoever.
	// For that reason we have to use the following two methods, to make at least TZ/DST
	// insensitive communication with the server possible.
	// Note: currently only works with resolutions down to the minute, not before year 1000 and not after the year 9999 ;-)
	getDateString: function(date) {
		return date.getFullYear().toString() +
			((date.getMonth() < 9) ? "0" : "") + (date.getMonth() + 1).toString() +
			((date.getDate() < 10) ? "0" : "") + date.getDate().toString() +
			((date.getHours() < 10) ? "0" : "") + date.getHours().toString() +
			((date.getMinutes() < 10) ? "0" : "") + date.getMinutes().toString();
	},
	getDateFromString: function(string) {
		if (!string) return null;
		return new Date(parseInt(string.substr(0,4),10), parseInt(string.substr(4,2),10)-1, parseInt(string.substr(6,2),10), parseInt(string.substr(8,2),10), parseInt(string.substr(10,2),10), 0, 0);
	},

	showTandemDialog: function(selectedTime, callback) {
		PCWN.tandemDialogCallback = callback;
		PCWN.tandemDialogSwitchToCalendar(false);

		var selectHour = function() {
			$("#tandemDialogSelection li").removeClass("selected");
			$(this).addClass("selected");
		}

		var updateSelection = function(animate) {
			var picker = $("#tandemDialogCalendar");
			var date = picker.datepicker("getDate");
			var data = picker.data("days")[PCWN.getDateString(date)];
			var html = "";
			for (var hour in data['hours']) {
				var hour = data['hours'][hour];
				html += "<li class=\"tandemSlot-" + hour.fuzzyAvailable + "\" time=\"" + hour.time + "\" location=\"" + hour.location + "\" available=\"" + hour.available + "\">" + hour.readable + ":00 (noch " + hour.available + " frei)";
				if (hour.location)
					html += "<br/>" + hour.location;
				html += "</li>";
			}
			$("#tandemDialogHourList").html("<ul>" + html + "</ul>");
			$("#tandemDialogSelectedDay").html($.datepicker.formatDate(PCWN.getMessage("dateFormat.datepicker.visible"),date));
			$("#tandemDialogSelection li").click(selectHour);
			PCWN.tandemDialogSwitchToHours(!picker.data("justOpening"));
		}

		$("#tandemDialogCalendar").data("justOpening",true);
		var startTime = selectedTime ? new Date(selectedTime.getTime()) : new Date();
		startTime.setDate(1);
		startTime.setHours(0);startTime.setMinutes(0);startTime.setSeconds(0);startTime.setMilliseconds(0);
		PCWN.postAjax({
			url: $("#tandemDialogCalendar").attr("updateUrl"),
			data: "start=" + PCWN.getDateString(startTime) + "&end=" + PCWN.getDateString(new Date(startTime.getTime() + 5356800000)), // +62 days
			success: function (data, textStatus) {
				$("#tandemDialogCalendar").data("days", data);
				$("#tandemDialogCalendar").datepicker({
					currentText: PCWN.getMessage("generic.today"),
					dayNamesMin: PCI18N["dayNamesMin"],
					firstDay: PCI18N["calendar.firstDay"],
					showButtonPanel: true,
					defaultDate: selectedTime || new Date(),
					monthNames: PCI18N["monthNames"],
					numberOfMonths: 2,
					beforeShowDay: function(date) {
						var day = $("#tandemDialogCalendar").data("days")[PCWN.getDateString(date)]
						if (day != null) {
							if (day.totalAvailable == 0)
								return [false,day.fuzzyAvailable,PCWN.getMessage("tandemDialog.available.none")]
							else if (day.totalAvailable == 1)
								return [true,day.fuzzyAvailable,PCWN.getMessage("tandemDialog.available.one")]
							else
								return [true,day.fuzzyAvailable,PCWN.getMessage("tandemDialog.available.more",[day.totalAvailable])]
						} else {
							return [false,"",""]
						}
					},
					onChangeMonthYear: function(year, month, picker) {
						if ($("#tandemDialogCalendar").data("justOpening")) return;
						$("#tandemDialogCalendar").datepicker("disable");
						var startTime = new Date(0);
						startTime.setYear(year);startTime.setMonth(month-1);
						PCWN.postAjax({
							async:false,
							url: $("#tandemDialogCalendar").attr("updateUrl"),
							data: "start=" + PCWN.getDateString(startTime) + "&end=" + PCWN.getDateString(new Date(startTime.getTime() + 5356800000)),
							success: function(data, textStatus) {
								$("#tandemDialogCalendar").data("days", data);
								$("#tandemDialogCalendar").datepicker("enable");
							}
						});
					},
					onSelect: updateSelection
				});
				if (selectedTime)
					updateSelection();
				$("#tandemDialog").dialog({
					bgiframe:true,
					modal:true,
					draggable: false,
					resizable: false,
					title: PCWN.getMessage("tandemDialog.title"),
					close: function (event, ui) {
						$("#tandemDialogCalendar").datepicker("destroy");
						$("#tandemDialog").dialog("destroy");
					},
					width:440,
					height:420
				});
				$("#tandemDialogCalendar").data("justOpening",false);
			}
		});
	},

	tandemDialogDoSelection: function() {
		var selectedItem = $("#tandemDialogSelection .selected:first");
		if (selectedItem.size() == 0) {
			PCWN.showErrorDialog(PCWN.getMessage("tandemDialog.error.selectTime"));
		} else if (selectedItem.attr("available") == "0") {
			PCWN.showErrorDialog(PCWN.getMessage("tandemDialog.error.noneAvailable"));
		} else if (PCWN.tandemDialogCallback == null) {
			location.href = $(this).attr("href") + "?time=" + selectedItem.attr("time");
		} else {
			$("#tandemDialog").dialog("destroy");
			PCWN.tandemDialogCallback(PCWN.getDateFromString(selectedItem.attr("time")),selectedItem.attr("location"));
		}
	},

	tandemDialogSwitchToCalendar: function(animate) {
		if (animate) {
			$("#tandemDialogTimeChooser").hide("slide",{direction:"right"});
			$("#tandemDialogDateChooser").show("slide");
		} else {
			$("#tandemDialogTimeChooser").hide();
			$("#tandemDialogDateChooser").show();
		}
	},

	tandemDialogSwitchToHours: function(animate) {
		if (PCWN.tandemDialogCallback == null) {
			$("#tandemDialogOptions").show();
			$("#tandemDialogChooseOptions").hide();
		} else {
			$("#tandemDialogOptions").hide();
			$("#tandemDialogChooseOptions").show();
		}
		if (animate) {
			$("#tandemDialogDateChooser").hide("slide");
			$("#tandemDialogTimeChooser").show("slide",{direction:"right"});
		} else {
			$("#tandemDialogDateChooser").hide();
			$("#tandemDialogTimeChooser").show();
		}
	},

	loadDialog: function(title, url) {
		$("#dialog")
		.html($("#pc-busyContent").html())
		.dialog({
			bgiframe:true,
			draggable: false,
			modal: true,
			resizable: false,
			title: title,
			width: 500,
			height: 400,
			close: function (event, ui) {
				$("#dialog").dialog("destroy")
			},
			open: function(event, ui) {
				var o = {};
				o[PCWN.getMessage("dialog.close")] = function() { $(this).dialog("close"); }
				$("#dialog").dialog("option", "buttons", o);
			}
		})
		.load(url);
	},

	getMessage: function(code, args) {
		if (!PCI18N[code])
			return code;
		if (!args)
			return PCI18N[code];
		var s = PCI18N[code];
		for (var i in args)
			s = s.replace("{"+i+"}", args[i]);
		return s;
	},

	updateWebcam: function() {
		$.get($("img.webcam").attr("updateUrl") + "?nocache=" + (new Date()).getTime(), function(data) {
			$("img.webcam").attr("src", data);
			window.setTimeout("PCWN.updateWebcam()", 5000);
		});
	}
}

/*
 * Load UI effects & widgets
 */
$(document).ready(function() {
	// Navigation Widget
	$(".navigation").addClass("ui-widget");
	$(".navigation > ul > li").each(function() { // top level items
		var item = $(this);
		var firstDiv = item.find("> div:first");
		firstDiv.addClass("ui-state-default");
		if (item.find("ul.subNavigation").length > 0) {
			// This is an opened "accordion" part
			firstDiv.addClass("ui-corner-top");
			item.find("ul.subNavigation").addClass("ui-widget-content ui-corner-bottom");
		} else {
			firstDiv.addClass("ui-corner-all");
		}
	});
	$(".navigation .ui-state-default")
	.hover(
		function(){
			$(this).addClass("ui-state-hover");
		},
		function(){
			$(this).removeClass("ui-state-hover");
		}
	).mousedown(
		function(){
			$(this).addClass("ui-state-active");
	}).mouseup(
		function(){
			$(this).removeClass("ui-state-active");
	});
	$(".navigation > ul > li").click(function() {
		location.href = $("a:first",this).attr("href");
	});

	// Toplevel Navigation
	$("#topNavigation div").click(function() {
		location.href = $("a:first",$(this)).attr("href");
	});

	// All clickables
	$(".pc-clickable")
	.addClass("ui-state-default ui-corner-all")
	.hover(
			function(){
				$(this).addClass("ui-state-hover");
			},
			function(){
				$(this).removeClass("ui-state-hover");
			}
		).mousedown(
			function(){
				$(this).addClass("ui-state-active");
		}).mouseup(
			function(){
				$(this).removeClass("ui-state-active");
		});

	// Lightbox

	// close everything with a click
	var hideLightbox = function() {
		$("#pc-lightboxContent").fadeOut(100);
		$("#pc-lightboxOverlay").fadeOut(100);
	}
	$("#pc-lightboxOverlay").click(hideLightbox);
	$("#pc-lightboxContent").click(hideLightbox);

	$("a.pc-lightbox").live("click", function() {
		// Position overlay and lightbox and fade them in
		var pageSizes = qm_getPageSize();
		var pageScrolls = qm_getPageScroll();
		$("#pc-lightboxOverlay")
			.css({width:pageSizes[0],height:pageSizes[1]})
			.css('filter', 'alpha(opacity=80)') // jQuerybug in IE - see http://stackoverflow.com/questions/1284163/jquery-ie-fadein-and-fadeout-opacity
			.fadeIn(200);
		$("#pc-lightboxContent")
			.css({width:"auto",height:"auto"})
			.html($("#pc-lightboxLoading").html())
			.css({
				left:Math.ceil((pageSizes[2] - $("#pc-lightboxContent").width()) / 2 + pageScrolls[0]),
				top:Math.ceil((pageSizes[3] - $("#pc-lightboxContent").height()) / 3 + pageScrolls[1]),
				width:$("#pc-lightboxContent").width(),
				height:$("#pc-lightboxContent").height()
				})
			.fadeIn(500);
		// Load the image
		var image = new Image();
		image.onload = function() {
			$("#pc-lightboxContent")
				.html("")
				.append(image);
			image.onload=function(){};
			var pageSizes = qm_getPageSize();
			$("#pc-lightboxContent")
				.stop(true,true)
				.animate({
					left:Math.ceil((pageSizes[2] - image.width) / 2 + pageScrolls[0]),
					top:Math.ceil((pageSizes[3] - image.height) / 3 + pageScrolls[1]),
					width:image.width,
					height:image.height
				}, "normal", "linear", function() { var pageSizes = qm_getPageSize(); $("#pc-lightboxOverlay").css({width:pageSizes[0],height:pageSizes[1]}); });
		};
		image.title = $(this).attr("title");
		image.src = $(this).attr("href");
		return false;
	});

	// Tandem pop-up
	$("#tandemSidebar li").click(function() {
		PCWN.showTandemDialog(PCWN.getDateFromString($(this).attr('time')));
		return false;
	});
	$("#tandemDialogTimeChooser .backToCalendar").click(function() {
		PCWN.tandemDialogSwitchToCalendar(true);
		return false;
	});
	$("#tandemDialogTimeChooser .makeAppointment, #tandemDialogTimeChooser .buyVoucher, #tandemDialogTimeChooser .chooseTime").click(function() {
		PCWN.tandemDialogDoSelection.apply(this);
		return false;
	});

	// Event pop-up
	$(".eventPopupLink").click(function() {
		PCWN.loadDialog($(this).attr("title"), $(this).attr("href"));
		return false;
	});

	// Member pop-up
	$("a.userDetailPopupLink").click(function() {
		PCWN.loadDialog($("img",this).attr("title"), $(this).attr("href"));
		return false;
	});

	// Backend keep-alive ping
	if ($('body').attr('pingUrl')) {
		var ping = function() {
			$.get($('body').attr('pingUrl'));
		}
		window.setInterval(ping, 1680000); // 28 minutes (30 minutes is the session timeout)
	}

	// Webcam
	if ($("img.webcam").length > 0) {
		window.setTimeout("PCWN.updateWebcam()", 5000);
	}

});

/*
 * helper methods from quirksmode.com
 *
 * @return Array Return an array with page width, height and window width, height
 */
function qm_getPageSize() {
	var xScroll, yScroll;
	if (window.innerHeight && window.scrollMaxY) {
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	var windowWidth, windowHeight;
	if (self.innerHeight) { // all except Explorer
		if (document.documentElement.clientWidth) {
			windowWidth = document.documentElement.clientWidth;
		} else {
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	} else if (document.documentElement
			&& document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}
	// for small pages with total height less then height of the viewport
	if (yScroll < windowHeight) {
		pageHeight = windowHeight;
	} else {
		pageHeight = yScroll;
	}
	// for small pages with total width less then width of the viewport
	if (xScroll < windowWidth) {
		pageWidth = xScroll;
	} else {
		pageWidth = windowWidth;
	}
	arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight);
	return arrayPageSize;
};

/*
 * helper methods from quirksmode.com
 *
 * @return Array Return an array with x,y page scroll values.
 */
function qm_getPageScroll() {
	var xScroll, yScroll;
	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
		xScroll = self.pageXOffset;
	} else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
		xScroll = document.documentElement.scrollLeft;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
		xScroll = document.body.scrollLeft;
	}
	arrayPageScroll = new Array(xScroll, yScroll);
	return arrayPageScroll;
};
