function Portal() {
	var _activeInlayElementId = "";
	var _locationSelectFormLoaded = false;
	var _overlayerActive = false;
	var _pageHowtoLoaded = false;
	var _activeTabId = null;
	var _geoLocationTippShowing = false;
	var _geoLocationTippStopDelay = false;
	var _hiddenFadeoutElements = null;
	
	this.getTotalOffsetTop = function(element, stopElement) {
		if (!element || element == stopElement) {
			return 0;
		} else {
			return element.offsetTop + this.getTotalOffsetTop(element.offsetParent, stopElement);
		}
	}
	
	this.getTotalOffsetLeft = function(element, stopElement) {
		if (!element || element == stopElement) {
			return 0;
		} else {
			return element.offsetLeft + this.getTotalOffsetLeft(element.offsetParent, stopElement);
		}
	}
	
	this.processMessageStatusResponse = function(json) {
		var container = $("divMessageStatusContainer");
		var newText = "";
		if (json >= 0) {
			// is it an update or is the status already shown?
			if ($("divMessageLiveUpdate").innerHTML != json) {
				$("divMessageLiveUpdate").innerHTML = json;
				// generate new status-text
				if (json == 0) {
					newText = "";
				} else {
					if (json == 1) {
						newText = "<a href=\"/messenger/messages/\" id=\"messagestatus\">Du hast eine neue Mitteilung!</a><br /><br />";
					} else if (json > 1) {
						newText = "<a href=\"/messenger/messages/\" id=\"messagestatus\">Du hast "+json+" neue Mitteilungen!</a><br /><br />";
					}
				}
				// build effect and start them
				var slideFx2 = new Fx.Slide(container, { 
					duration: 500,
					onComplete: function() {
						portal.blinkMessageStatus();
					}
				});			
				var slideFx1 = new Fx.Slide(container, { 
					duration: 800,
					onComplete: function() {
						container.innerHTML = newText;
						slideFx2.slideIn();
					}	
				});
				slideFx1.slideOut();				
			}
			portal.delayedLoadMessageStatus();
		}
	}
	
	this.blinkMessageStatus = function(i) {
		i = typeof(i) != 'undefined' ? i+1 : 1;
		var myFx = new Fx.Morph('messagestatus', {
			duration: 500,
			transition: Fx.Transitions.linear,
			onComplete: function() {
				if (i < 6) { portal.blinkMessageStatus(i); }
			}
			
		});		
		var color1 =  (i % 2 == 0) ? '#13488A' : '#ffffff';
		var color2 =  (i % 2 == 1) ? '#13488A' : '#ffffff';
		myFx.start({'color': [color1, color2]});
	}
	
	this.delayedLoadMessageStatus = function() {
		window.setTimeout("portal.loadMessageStatus()", 30000);
	}
	
	this.loadMessageStatus = function() {
		if ($("divMessageLiveUpdate")) {
			new Request.JSON({url: "/", onComplete: portal.processMessageStatusResponse}).get({'callback': 'messenger/status'});
		}
	}
	
	this.lastLoginedUsersLoad = function(modifier) {
		var container = $("lastLoginedUsersContainer");
		var offsetContainer = $("lastLoginedUsersCurrentOffset");
		var limitContainer = $("lastLoginedUsersCurrentLimit");
		var data = $("lastLoginedUsersData");
		var controls = $("lastLoginUsersControls");
		
		if (modifier == "+") {
			slideAwayPosition = -130;
			reposition = 130;
		} else {
			slideAwayPosition = 130;
			reposition = -130;
		}
		
		var slowFx = new Fx.Tween(container, { duration: 500, transition: Fx.Transitions.Quad.easeInOut });
		var fastFx = new Fx.Tween(container, { duration: 250, transition: Fx.Transitions.Quad.easeInOut });
				
		// slide data away
		slowFx.start('left', 0, slideAwayPosition).chain(function() {
			// hide wrapper and reposition it on the other side
			container.style.display = 'none';
			container.style.left = reposition+"px";
			container.style.display = '';			
			// set status and hide controls
			data.innerHTML = $('lastLoginedUsersLoading').innerHTML;
			controls.style.display = "none";
			//slide status in			
			fastFx.start('left', reposition, 0).chain(function() {
				new Request.JSON({
					url: "/", 
					onComplete: portal.processLastLoginedUsersResponse
				}).get({'callback': 'generic/lastloginedusers', 'offset': offsetContainer.innerHTML, 'limit': limitContainer.innerHTML, 'modifier': modifier});
			})
		});
	}
	
	this.processLastLoginedUsersResponse = function(json) {
		var container = $("lastLoginedUsersContainer");
		var data = $("lastLoginedUsersData");
		var controls = $("lastLoginUsersControls");
		var offsetContainer = $("lastLoginedUsersCurrentOffset");
		var limitContainer = $("lastLoginedUsersCurrentLimit");
		var countContainer = $("lastLoginedUsersCurrentCount");
		
		if (json.modifier == "+") {
			slideAwayPosition = -130;
			reposition = 130;
		} else {
			slideAwayPosition = 130;
			reposition = -130;
		}
		
		var slowFx = new Fx.Tween(container, { duration: 500, transition: Fx.Transitions.Quad.easeInOut });
		var fastFx = new Fx.Tween(container, { duration: 250, transition: Fx.Transitions.Quad.easeInOut });
		
		offsetContainer.innerHTML = json.offset;
		limitContainer.innerHTML = json.limit;
		countContainer.innerHTML = json.count;
		
		if (json.offset == 0) {
			$("lastLoginedUsersPrevLinkContainer").innerHTML = '';
		} else {
			$("lastLoginedUsersPrevLinkContainer").innerHTML = '<img src="/images/layout/sideleftnavpoint.png" alt="" /> <a href="javascript:portal.lastLoginedUsersLoad(\'-\')">zurück</a>';
		}
		if ((parseInt(json.offset)+parseInt(json.limit)) > countContainer.innerHTML) {
			$("lastLoginedUsersNextLinkContainer").innerHTML = '';
		} else {
			$("lastLoginedUsersNextLinkContainer").innerHTML = '<a href="javascript:portal.lastLoginedUsersLoad(\'+\')" style="float:left">weiter</a>&nbsp;<img src="/images/layout/sidenavpoint.png" alt="" />';
		}		
		
		// slide status away
		fastFx.start('left', 0, slideAwayPosition).chain(function() {
			// hide wrapper and reposition it on the other side
			container.style.display = 'none';
			container.style.left = reposition+"px";
			container.style.display = '';			
			// set data and show controls
			data.innerHTML = json.content;	
			controls.style.display = "";
			// slide data back in
			slowFx.start('left', reposition, 0).chain(
					// build tooltips on the new data
					portal.prepareTooltips('lastLoginedUsersData')
			);
		});
	}
	
	this.validateSession = function() {
		new Request({url: "/"}).send('callback=generic/session');
	}
	
	this.loadJs = function(url) {
		var exists = false;
		for (i in document.getElementsByTagName("script")) {
			var src = document.getElementsByTagName("script")[i].src;
			if (src && src.lastIndexOf(url) != -1) {
				exists = true;
			}
		}
		if (!exists) {
			var scriptTag = document.createElement("script");
			scriptTag.type = "text/javascript";
			scriptTag.src = url;
			document.getElementsByTagName("head")[0].appendChild(scriptTag);
		}
	}
	
	this.showLocationSelect = function(focus) {
		if (!_locationSelectFormLoaded) {
			if (window.location.pathname != "/user/selectlocation/") {
				document.cookie = 'requestUri='+window.location.pathname+'; path=/';
			}
			portal.loadJs("/js/intellitype.js?neulad=ja");
			_locationSelectFormLoaded = true;
			new Request.HTML({onComplete: function(responseTree, responseElements, responseHTML, responseJavaScript, focus) { $('locationSelect').innerHTML = responseHTML; if(focus) {$('location_assistanceField').focus();} }}).get("/user/locationselectform/");
		}
		
		var effect = new Fx.Morph("locationSelect", {duration: 750, transition: Fx.Transitions.Sine.easeOut});
		effect.start({'opacity': [0, 0.85], 'display': "block"});		
	}
	
	this.showOverlayPage = function(page, title, allowClose) {
		if ($('overlayerStatus').innerHTML != page) {			
			$('overlayerStatus').innerHTML = page;
			$('overlayerContent').innerHTML = '<div style="text-align:center"><img src="/images/layout/ajax-loader.gif" alt="" style="margin-bottom:5px" /><br />Die Ladeanimation dreht sich minutenlang, aber es passiert nichts weiter? In diesem Fall kannst Du mit dem "x" rechts dieses Fenster schließen!</div>';
			new Request.HTML({onComplete: function(responseTree, responseElements, responseHTML, responseJavaScript) { $('overlayerContent').innerHTML = responseHTML; }}).get(page);
		}
		if (_overlayerActive == false) {
			if (title != null) {
				$('overlayer').getChildren()[0].getChildren()[1].innerHTML = title+"  <a id='closelink' href='#' onclick='_closeOverlayer()'>x</a>";
			}
			portal.fadeOutPage('overlayer', allowClose == true);
			_overlayerActive = true;
		}
	}
	
	this.resizeFadeOutOverlay = function() {
		var layer = $("portalOverlay");
		if (layer) {
			var arrayPageSize = portal.getPageSize();
			layer.style.width = arrayPageSize[0] + "px";
			layer.style.height = arrayPageSize[1] + "px";
			$(_activeInlayElementId).style.left = (arrayPageSize[0]/2-$(_activeInlayElementId).offsetWidth/2)+"px";
		}
	}
	
	this.fadeOutPage = function(inlayElementId, allowClose) {
		var arrayPageSize = this.getPageSize();
		var layer = document.createElement("div");
		if (allowClose) {
			layer.onclick = new Function("portal.fadeInPage('"+inlayElementId+"')");
		}
		layer.setAttribute("id", "portalOverlay");
		layer.style.backgroundColor = "#000000";
		layer.style.zIndex = 1000;
		layer.style.position = "absolute";
		layer.style.top = "0px";
		layer.style.left = "0px";
		layer.style.display = "none";
		layer.style.width = arrayPageSize[0] + "px";
		layer.style.height = arrayPageSize[1] + "px";
		$("body").appendChild(layer);
		
		_hiddenFadeoutElements = new Array();
		var hideElements = $$('select');
		hideElements = hideElements.concat($$('embed'));
		for (var i=0; i<hideElements.length; i++) {
			var id = hideElements[i].getAttribute("id");
			if (hideElements[i].style.visibility != "hidden" && id != "location" && id != "radius" && id != "region") {
				hideElements[i].style.visibility = "hidden";
				_hiddenFadeoutElements.push(hideElements[i]);
			}
		}
		
		var effect = new Fx.Morph("portalOverlay", {duration: 500, transition: Fx.Transitions.Sine.easeOut});
		effect.start({'opacity': [0, 0.5], 'display': "block"});
		
		var effect2 = new Fx.Morph(inlayElementId, {duration: 500, transition: Fx.Transitions.Sine.easeOut});
		effect2.start({'opacity': [0, 1]});
		$(inlayElementId).style.display = "inline";
		$(inlayElementId).style.left = (arrayPageSize[0]/2-$(inlayElementId).offsetWidth/2)+"px";
		window.addEvent('resize', portal.resizeFadeOutOverlay);
		_activeInlayElementId = inlayElementId;
	}
	
	this.fadeInPage = function(inlayElementId) {
		if ($("portalOverlay")) {
			_overlayerActive = false;
			$('overlayer').getChildren()[0].getChildren()[1].innerHTML = "Wird geladen - Bitte warten <a id='closelink' href='#' onclick='_closeOverlayer()'>x</a>";
			
			var effect2 = new Fx.Morph(inlayElementId, {duration: 500, onComplete: function() { $(inlayElementId).style.display = "none"; }});
			effect2.start({'opacity': [1, 0]});
			var effect = new Fx.Morph("portalOverlay", {duration: 500, onComplete: function() { $("body").removeChild($("portalOverlay")); }});
			effect.start({'opacity': [0.5, 0]});
			
			for (var i=0; i<_hiddenFadeoutElements.length; i++) {
				_hiddenFadeoutElements[i].style.visibility = "visible";
			}
		}
	}
	
	this.setClassnameToNode = function(node, classname) {
		var classNode = document.createAttribute("class");
		classNode.nodeValue = classname;
		node.setAttributeNode(classNode);
	}
	
	this.openTab = function(tabId, dontUpdateTabbar) {
		if (tabId != _activeTabId) {
			$('tabContent_'+_activeTabId).style.display = "none";
			$('tabContent_'+tabId).style.display = "block";
			if (!dontUpdateTabbar) {
				portal.setClassnameToNode($('tab_'+_activeTabId), 'tabentry inactive');
				portal.setClassnameToNode($('tab_'+tabId), 'tabentry active');
				portal.setClassnameToNode($('tabstyle_pastactive'), 'left leftnormal');
			}
			_activeTabId = tabId;
		}
	}
	
	this.setInitialTab = function(tabId) {
		_activeTabId = tabId;
	}
		
	// Returns array with page width, height and window width, height
	// Core code from - quirksmode.com
	// Edit for Firefox by pHaez
	this.getPageSize = function() {
		var xScroll
		var 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
		var 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;
	}
	
	this.openFeedbackWindow = function() {
		var currentPagePath = window.location.pathname;
		var previousPagePath = document.referrer;
		if (previousPagePath) {
			previousPagePath = previousPagePath.replace(/http:\/\/g3.geknipst.at/, "");
		}
		var win = window.open("/geknipst/betafeedback/current/"+encodeURIComponent(currentPagePath)+"/previous/"+encodeURIComponent(previousPagePath)+"/", "betafeedback", "dependent=yes,height=500,location=no,menubar=no,resizable=yes,scrollbars=yes,status=no,toolbar=no,width=500");
	}
	
	this.prepareTooltips = function(onlyInCSSSelector) {
		var tips = new Tips('.imgtip', {className: "imgtip", offsets: {x: 16, y: -6}});
		
		if (onlyInCSSSelector == null) {
			var el = $$('.imgtip');
		} else {
			var el = $(onlyInCSSSelector).getElements('.imgtip');
		}
		
		el.each(function(tip){
			var imgSrc = tip.retrieve('tip:text');
			var imgAlt = tip.retrieve('tip:title');
			tip.store('tip:text', new Element('img',{'src':imgSrc,'alt':imgAlt}));
		});
	}
	
	this.displayLateLoadAds = function() {
		$$('.lateLoad').each(function(el){
			$(el.get('rel')).innerHTML = el.innerHTML;
			el.innerHTML = "";
		});
	}
	
	window.addEvent('domready', this.prepareTooltips);	
	window.addEvent('domready', this.delayedLoadMessageStatus);
	window.addEvent('domready', this.displayLateLoadAds);
}

var portal = new Portal();