﻿var Session = {
	cookie_name: "CH.Session",
	timeout: null,

	register: function (timeout) {
		this.timeout = timeout;
		$.cookie(this.cookie_name, new Date().getTime(), { path: "/" });
	},

	authenticated: function () {
		return this.remaining() > 0;
	},

	remaining: function () {
		var expire = this.time() + this.timeout;
		var remaining = expire - new Date().getTime();
		return remaining > 0 ? remaining : 0;
	},

	time: function () {
		var val = $.cookie(this.cookie_name);
		return val ? parseFloat(val) : new Date().getTime();
	},

	dialog: function (content, settings) {
		var defaults = {
			modal: true,
			resizable: false,
			close: function () { $d.dialog("destroy").remove(); }
		};
		$.extend(defaults, settings);

		var $d = $("<div tabIndex='-1' style='outline-width: 0'></div>").html(content).dialog(defaults).focus();
		return $d;
	},

	alert: function (content, onclose) {
		var $d = this.dialog(content, {
			title: "Alert",
			close: function () { if (onclose) onclose(); $d.dialog("destroy").remove(); },
			buttons: {
				"Ok": function () { $d.dialog("close"); }
			}
		}).keypress(function (e) {
			if (e.keyCode == 13) $d.dialog("close");
		});
	},

	confirm: function (content, response) {
		var $d = this.dialog(content, {
			title: "Confirm",
			buttons: {
				"Cancel": function () { response(false); $d.dialog("close"); },
				"Ok": function () { response(true); $d.dialog("close"); }
			}
		});
	}
}

Session.Notify = function (params) {
	var self = this;
	var timeout = params.timeout * 60 * 1000;
	var warning = params.warning * 60 * 1000;
	var redirect = params.redirect;
	var authenticate = params.authenticate;
	var mode = params.mode;
	var userId = params.userId;
	var base = params.base;
	var timeout_id = null;
	var $dialog = null;
	var state = Session.Notify.State.hidden;
	var ignore = false;

	function init() {
		register();
		check(timeout - warning);
	}

	function register() {
		Session.register(timeout);
	}

	function check(timeout) {
		timeout_id = window.setTimeout(function () {
			if (ignore) return;
			var remaining = Session.remaining();

			if (remaining > warning) {
				// Session has been reauthenticated through another request after session was registered
				close(true);
				check(remaining - warning);
				return;
			}

			if (remaining > 0) {
				// Warn the user
				if (state != Session.Notify.State.warning) {
					dialog("<p>Your session is about to expire.</p><p>Click <strong>continue</strong> to renew your session.</p>", {
						title: "Warning",
						close: function () {
							// Reauth
							$.get(authenticate, { cmd: "refresh" }, function () {
								register();
							});
							remove();
						},
						buttons: {
							"Continue": function () {
								close();
							}
						}
					}, close);
					state = Session.Notify.State.warning;
				}
				check(remaining);
				return;
			}

			// Session expired
			if (state != Session.Notify.State.expired) {
				if (mode == Session.Notify.Mode.redirect) {
					var html = [];
					html.push("<div>");
					html.push("<p>Your session has expired</p>");
					html.push("<div style='background: #F7F7F7; padding: 5px; border: solid 1px #B8B8B8;'><table style='margin: 0 auto;'>");
					html.push("<tr><td><input type='radio' id='window-current' checked='true' name='window' value='current' /></td><td><label for='window-current'>login using current window</label></td></tr>");
					html.push("<tr><td><input type='radio' id='window-new' name='window' value='new' /></td><td><label for='window-new'>login using new window</label></td></tr>");
					html.push("</table></div>");
					html.push("</div>");

					var $content = $(html.join(''));

					var login = function () {
						if ($content.find(":checked").val() == "current") {
							location.href = redirect;
						} else {
							window.open(redirect);
						}
					}

					dialog($content, {
						title: "Session Expired",
						buttons: {
							"Ignore": function () {
								close();
								ignore = true;
							},
							"Login": function () {
								login();
							}
						}
					}, login);

				} else {
					var html = [];
					html.push("<div>");
					html.push("<p>Please login using the fields below to continue with your session.</p>");
					html.push("<div id='session-notify-fields' style='background: #F7F7F7 no-repeat center center; padding: 10px; border: solid 1px #B8B8B8;'><table style='margin: 0 auto;'>");
					html.push("<tr><td style='width: 30%'><label for='session-notify-username'>Username:</label></td><td style='width: 70%'><input style='width: 99%' type='text' id='session-notify-username' /></td></tr>");
					html.push("<tr><td><label for='session-notify-password'>Password:</label></td><td><input style='width: 99%' type='password' id='session-notify-password' /></td></tr>");
					html.push("</table></div>");
					html.push("<p>If this was not your session, <a href='" + redirect + "'>login here</a>.</p>");
					html.push("</div>");

					var $content = $(html.join(''));
					var $username = $content.find("input:eq(0)");

					var login = function () {
						var $fields = $content.find("#session-notify-fields");
						$fields.find("table").css("visibility", "hidden");
						$fields.css("background-image", "url(" + base + "common/style/images/ajax_loader.gif)");

						var end = function () {
							$fields.find("table").css("visibility", "visible");
							$fields.css("background-image", "none");
						}

						var username = $username.val();
						var password = $content.find("input:eq(1)").val();

						var args = {
							cmd: "login",
							username: username,
							password: password,
							lastUserId: userId
						}

						$.ajax({
							url: authenticate,
							type: "POST",
							data: args,
							dataType: "text",
							success: function (response) {
								end();
								var valid = response == "True";

								if (!valid) {
									var html = [];
									html.push("<div style='color: #B32424'>");

									if (response == "DiffUser") {
										html.push("<p>You are attempting to login with a user account that does not match the previously logged in user.</p>");
										html.push("<p>Please use <a href='" + redirect + "'>this link</a> to login with your account.</p>");
									} else {
										html.push("<div style='text-align: center'><p>Invalid Login</p></div>");
									}
									html.push("</div>");

									Session.alert(html.join(''), function () { $username.select(); });
									return;
								}

								register();
								$dialog.dialog("option", "beforeClose", function () { return true; });
								close();
							},
							error: function () {
								end();
								Session.alert("A problem occurred during authentication. Please try again.", function () { $username.select(); });
							}
						});
					};

					var $d = dialog($content, {
						title: "Session Expired",
						beforeClose: function () { return false; },
						buttons: {
							"Login": function () {
								login();
							}
						}
					}, login);

					// Hide close button
					$d.closest(".ui-dialog").find(".ui-dialog-titlebar-close").hide();

					$username.focus();
				}

				state = Session.Notify.State.expired;
			}

			// Keep checking in case the session was registered again after we got to this stage
			check(1000);

		}, timeout);
	}

	function dialog(content, settings, enter) {
		if ($dialog) {
			close(true);
		}

		var defaults = {
			close: function () { remove() }
		}
		$.extend(defaults, settings);

		$dialog = Session.dialog(content, defaults);
		if (enter) {
			$dialog.keypress(function (e) {
				if (e.keyCode == 13) enter();
			});
		}

		return $dialog;
	}

	function close(bypass) {
		state = Session.Notify.State.hidden;

		if ($dialog) {
			if (bypass) {
				$dialog.dialog("option", "beforeClose", function () { return true; });
				$dialog.dialog("option", "close", function () { remove() });
			}

			$dialog.dialog("close");
			$dialog = null;
		}
	}

	function remove() {
		$dialog.dialog("destroy").remove();
	}

	init();
}

Session.Notify.State = {
	hidden: 0,
	warning: 1,
	expired: 2
}

Session.Notify.Mode = {
	redirect: 0,
	direct: 1
}

Session.Notify.init = function (params) {
	return new Session.Notify(params);
}
