﻿SessionTimeout = {

	initialised: false,
	authenticateUrl : null,
	request : null,
	timeoutInterval : null,
	lastUserId : null,
	timeoutIdentifier: null,
	
	lastActiveCookieName : "stLastActive",
	lastActiveDate : new Date(),
	
	// Form
	loginForm : null,
	loginFormPollIdentifier : null,
	loginFormCuttoffOpacity : 1,
	loginFormOpacityIntervalDivider : 15,
	
	// Form elements
	processingMsg : null,
	errorMsg : null,
	usernameField : null,
	passwordField : null,
	diffUserLoginLink : null,	
	
	// Lock Management
	lock : null,
	lockPollIdentifier : null,
	lockCuttoffOpacity : 0.75,
	lockOpacityIntervalDivider : 5,
	iframe : null,
		
	init : function(authenticateUrl, timeoutInterval, lastUserId, formId, loginBtnId, processingMsgId, errorMsgId, usernameFieldId, passwordFieldId, diffUserLoginLink) {
		if(typeof RequestHandler == "undefined") throw "SessionTimeout requires RequestHandler class";
		if(typeof Window == "undefined") throw "SessionTimeout requires Window class";
		if(typeof Cookies == "undefined") throw "SessionTimeout requires Cookies class";
		if(SessionTimeout.initialised) throw "SessionTimeout has already been initialised";
		
		// Set properties
		SessionTimeout.initialised = true;	
		SessionTimeout.authenticateUrl = authenticateUrl;
		SessionTimeout.timeoutInterval = timeoutInterval;
		SessionTimeout.lastUserId = lastUserId;
		SessionTimeout.lastActiveCookieName += lastUserId;
		SessionTimeout.diffUserLoginLink = diffUserLoginLink;
		SessionTimeout.request = new RequestHandler(SessionTimeout.authenticateUrl)
		
		// Init form
		SessionTimeout.initForm(formId, loginBtnId, processingMsgId, errorMsgId, usernameFieldId, passwordFieldId);
		
		// Set events
		Cookies.add(new Cookie(SessionTimeout.lastActiveCookieName, SessionTimeout.lastActiveDate.toGMTString(), null, "/"));
		EventManager.attach(window, "resize", SessionTimeout.resizeLock);
		SessionTimeout.timeoutIdentifier = window.setTimeout(SessionTimeout.timeout, 1000 * SessionTimeout.timeoutInterval * 60);
	},
	
	initForm : function(formId, loginBtnId, processingMsgId, errorMsgId, usernameFieldId, passwordFieldId) {
		// Login form
		SessionTimeout.loginForm = document.getElementById(formId);
		if(SessionTimeout.loginForm == null) throw "Form with id: " + formId + " could not be found";
		SessionTimeout.toggleDisplay(SessionTimeout.loginForm, false);
		
		// Processing message
		SessionTimeout.processingMsg = document.getElementById(processingMsgId);
		if(SessionTimeout.processingMsg == null) throw "Processing message element with id: " + processingMsgId + " could not be found";
		
		// Error message
		SessionTimeout.errorMsg = document.getElementById(errorMsgId);
		if(SessionTimeout.errorMsg == null) throw "Error message element with id: " + errorMsgId + " could not be found";
		
		// Set login button click event
		var loginButton = document.getElementById(loginBtnId);
		if(loginButton == null) throw "LoginBtn with id: " + loginBtnId + " could not be found";
		loginButton.onclick = function(e) { SessionTimeout.login_click(e);return false; };
		
		// Username field
		SessionTimeout.usernameField = document.getElementById(usernameFieldId);
		if(SessionTimeout.usernameField == null) throw "Username field with id: " + usernameFieldId + " could not be found";
		
		// Password field
		SessionTimeout.passwordField = document.getElementById(passwordFieldId);
		if(SessionTimeout.passwordField == null) throw "Password field with id: " + passwordFieldId + " could not be found";
	},
	
	timeout : function() {
		// Check if other windows have been opened and renewed the session
		var active = SessionTimeout.getActiveDate();
		if(active != null) {
			SessionTimeout.cleanup(active);
			return;
		}		
		SessionTimeout.showForm();
	},
	
	getActiveDate : function() {
		var lastActive = Cookies.get(SessionTimeout.lastActiveCookieName);
		if(lastActive != null) {
			var active = new Date(lastActive.value); 
			if(SessionTimeout.lastActiveDate < active) {
				return active;
			}
		}
		return null;	
	},
	
	showForm : function() {
		if(SessionTimeout.isLoginFormActive()) SessionTimeout.cleanup();
	
		if(SessionTimeout.isIE6()) {
			// This is only needed for ie6 to prevent form elements from appearing
			// above lock element - note: make sure its not activated on opera as it lags out serverely 
			SessionTimeout.iframe = document.createElement("iframe");
			var iframe = SessionTimeout.iframe;
			iframe.style.width = Window.getScrollWidth() + "px";
			iframe.style.height = Window.getScrollHeight() + "px";				
			iframe.style.position = "absolute";
			iframe.style.top = "0px";
			iframe.style.left = "0px";
			iframe.style.zIndex = "8888";
			iframe.src = "javascript:'<html></html>';";
			SessionTimeout.setOpacity(iframe, 0);
			document.body.appendChild(iframe);
		}
		
		// Create lock element to obscure/prevent interaction with page
		SessionTimeout.lock = document.createElement("div");
		var lock = SessionTimeout.lock;
		lock.id = "lockElement";			
		lock.style.position = "absolute";
		lock.style.top = "0px";
		lock.style.left = "0px";
		lock.style.width = Window.getScrollWidth() + "px";
		lock.style.height = Window.getScrollHeight() + "px";
		lock.style.zIndex = "8888";
		SessionTimeout.setOpacity(lock, 0);
		document.body.appendChild(lock);
		
		// Move login form to last element of body (prevent incorrect positioning of relative
		// and ensures highest displayed element - important for ie6
		var loginForm = SessionTimeout.loginForm;	
		loginForm.parentNode.removeChild(loginForm);
		document.body.appendChild(loginForm);
		SessionTimeout.toggleDisplay(SessionTimeout.processingMsg, false);
		SessionTimeout.toggleDisplay(SessionTimeout.errorMsg, false);		
		SessionTimeout.toggleDisplay(loginForm, true);
		loginForm.style.zIndex = "9999";
		loginForm.style.position = "absolute";
		SessionTimeout.setOpacity(loginForm, 0);
		SessionTimeout.usernameField.value = "";
		SessionTimeout.passwordField.value = "";
		SessionTimeout.usernameField.focus();
			
		SessionTimeout.setLoginFormSettings(true);		
		SessionTimeout.setLockSettings();
	},
	
	setLoginFormSettings : function(init) {
		var active = SessionTimeout.getActiveDate();
		if(active != null) {
			SessionTimeout.cleanup(active);
			return;
		}
	
		var viewport = Window.getViewport();
		var scroll = Window.getScroll();
		var loginForm = SessionTimeout.loginForm;
		
		// Calculate where we want the box to be moved
		var moveToX = viewport.width / 2 - (loginForm.offsetWidth / 2) + scroll.left;
		var moveToY = viewport.height / 2 - (loginForm.offsetHeight / 2) + scroll.top;
		
		if(init) {
			loginForm.style.left = moveToX + "px";
			// Place form at bottom of screen so it slides up into the center
			loginForm.style.top = (viewport.height / 2) + scroll.top + "px";
			
		} else {	
			// Find the difference between current position and moveto position, and soften :)
			var currX = loginForm.offsetLeft;
			var currY = loginForm.offsetTop;
			
			// Check if we still need to move vertical
			if(moveToY == currY || Math.abs(moveToY - currY) > moveToY / 50) {
				var yDiff = moveToY - currY;
				loginForm.style.top = currY + (yDiff / 5) + "px";
			}
			
			// Check if we still need to move horizontal
			if(moveToX == currX || Math.abs(moveToX - currX) > moveToX / 50) {
				var xDiff = moveToX - currX;
				loginForm.style.left = currX + (xDiff / 5) + "px";
			}
			
			SessionTimeout.shiftOpacity(loginForm, SessionTimeout.loginFormOpacityIntervalDivider, SessionTimeout.loginFormCuttoffOpacity);
		}
		
		SessionTimeout.loginFormPollIdentifier = window.setTimeout(function() {SessionTimeout.setLoginFormSettings();}, 20);	
	},
	
	setLockSettings : function() {	
		if(!SessionTimeout.shiftOpacity(SessionTimeout.lock, SessionTimeout.lockOpacityIntervalDivider, SessionTimeout.lockCuttoffOpacity)) {
			window.clearTimeout(SessionTimeout.lockPollIdentifier);
			return;
		}	
		SessionTimeout.lockPollIdentifier = window.setTimeout(SessionTimeout.setLockSettings, 20);	
	},
	
	resizeLock : function() {
		var lock = SessionTimeout.lock;
		if(lock == null) return;
		
		// Makes sure its the correct width if screen resized
		var page = Window.getPage();
		
		if(lock.offsetWidth != page.width) lock.style.width = page.width + "px";
		if(lock.offsetHeight != page.height) lock.style.height = page.height + "px";
	},
	
	login_click : function(e) {
		if(SessionTimeout.request.isProcessing()) {
			alert("Please wait for the request to be processed");
			return;
		}
		
		SessionTimeout.toggleDisplay(SessionTimeout.processingMsg, true);
		SessionTimeout.toggleDisplay(SessionTimeout.errorMsg, false);
			
		var username = document.getElementById("username").value;
		var password = document.getElementById("password").value;
		
		var cmd = new Command("login", SessionTimeout.handleAuthResponse);
		cmd.args.push(username);
		cmd.args.push(password);
		cmd.args.push(SessionTimeout.lastUserId);
		
		SessionTimeout.request.doCommand(cmd);				
	},
	
	handleAuthResponse : function(command, response) {
		if(!command.validResponse()) {
			alert("There was a problem sending the authentication request.\nIf this continues please contact CareerHub support.");
			SessionTimeout.toggleDisplay(SessionTimeout.processingMsg, false);
			SessionTimeout.toggleDisplay(SessionTimeout.errorMsg, false);
			return;
		}
	
		var valid = response == "True";
		
		if(!valid) {
			SessionTimeout.toggleDisplay(SessionTimeout.processingMsg, false);
			
			var message = "Invalid Login";
			if(response == "DiffUser") {
				message = "You are attempting to login with a user account that does not match the previously logged in user." + 
				" Please use <a href=\"" + SessionTimeout.diffUserLoginLink + "\">this link</a> to login with your account.";
			}
			SessionTimeout.errorMsg.innerHTML = message;
			
			SessionTimeout.toggleDisplay(SessionTimeout.errorMsg, true);
			return;
		}
		
		Cookies.add(new Cookie(SessionTimeout.lastActiveCookieName, new Date().toGMTString(), null, "/"));
		SessionTimeout.cleanup();
	},
	
	cleanup : function(lastActive) {
		window.clearTimeout(SessionTimeout.loginFormPollIdentifier);
		window.clearTimeout(SessionTimeout.lockPollIdentifier);
		window.clearTimeout(SessionTimeout.timeoutIdentifier);
		
		// Hide login form for next display
		SessionTimeout.toggleDisplay(SessionTimeout.loginForm, false);
		SessionTimeout.toggleDisplay(SessionTimeout.processingMsg, false);
		
		// Remove lock
		if(SessionTimeout.lock != null) {
			SessionTimeout.lock.parentNode.removeChild(SessionTimeout.lock);
			SessionTimeout.lock = null;
		}
		
		// Remove iframe hack if implemented
		if(SessionTimeout.iframe != null) {
			SessionTimeout.iframe.parentNode.removeChild(SessionTimeout.iframe);
			SessionTimeout.iframe = null;
		}
		
		// Reset timeout
		SessionTimeout.lastActiveDate = new Date();
		var timeout = SessionTimeout.timeoutInterval * 1000 * 60;
		if(lastActive != null) timeout = timeout - (SessionTimeout.lastActiveDate.getTime() - lastActive.getTime());
			
		SessionTimeout.timeoutIdentifier = window.setTimeout(SessionTimeout.timeout, timeout);
	},
	
	shiftOpacity : function(element, increment, cuttoff) {
		if(element.currOpacity == cuttoff || Math.abs(cuttoff - element.currOpacity) < cuttoff / 25) {
			SessionTimeout.setOpacity(element, cuttoff);
			return false;
		}
		
		var shift = cuttoff / increment;//(cuttoff - element.currOpacity) / increment;
		var opacity = element.currOpacity + shift;
		SessionTimeout.setOpacity(element, opacity);
		
		return true;
	},
		
	setOpacity : function(element, opacity) {
		element.style.filter = "alpha(opacity=" + (opacity * 100) + ")";
		element.style.MozOpacity = opacity;
		element.style.opacity = opacity;
		element.currOpacity = opacity;
	},
	
	isLoginFormActive : function() {
		return SessionTimeout.lock != null;
	},
	
	toggleDisplay : function(element, show) {
		element.style.display = show ? "block" : "none";
	},
	
	isIE6 : function() {
		var ua = navigator.userAgent.toLowerCase();
		var isIE = (ua.indexOf("msie") != -1) && (ua.indexOf("opera") == -1) && (ua.indexOf("webtv") == -1);
		return isIE && typeof document.body.style.maxHeight == "undefined";
	}
}
