<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Terminal</title>
<link rel="stylesheet" href="/_ssh/xterm.css" />
<style>
	body {
		margin: 0;
		height: 100%;
	}

	#terminal-container {
		display: flex;
		flex-direction: column;
		width: 100%;
		height: 100vh;
	}

	#terminal-info-container {
		vertical-align: middle;
		padding: 3px;
	}

	#terminal-target {
		display: inline-block;
		height: 100%;
		vertical-align: middle;
	}

	#terminal-status {
		display: inline-block;
		font-weight: bold;
		height: 100%;
		vertical-align: middle;
	}

	#terminal-errmsg {
		display: inline-block;
		color: red;
		height: 100%;
		vertical-align: middle;
	}

	#terminal-control {
		display: inline-block;
		height: 100%;
		vertical-align: middle;
	}

	#terminal-control button {
		vertical-align: middle;
	}

	#terminal-view-container {
		flex: 1;
		width: 100%;
		min-height: 0;
		/*height: 100%;*/
	}

	#login-container {
		display: flex;
		justify-content: center;
		align-items: center;
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		background-color: rgba(0, 0, 0, 0.5);
		z-index: 99999;
	}
	#login-form-container {
		background: white;
		padding: 20px;
		border-radius: 8px;
		box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
		text-align: center;
	}
	#login-form-title {
		line-height: 2em;
		font-size: 2em;
		font-weight: bold;
	}
</style>
<script src="/_ssh/xterm.js"></script>
<script src="/_ssh/xterm-addon-fit.js"></script>

<script>
const conn_id = '{{ .ConnId }}';
const route_id = '{{ .RouteId }}';

window.onload = function(event) {
	const terminal_container = document.getElementById('terminal-container');
	const terminal_target = document.getElementById('terminal-target');
	const terminal_status = document.getElementById('terminal-status');
	const terminal_errmsg = document.getElementById('terminal-errmsg');
	const terminal_view_container = document.getElementById('terminal-view-container');
	const terminal_disconnect = document.getElementById('terminal-disconnect');
	const login_container = document.getElementById('login-container');
	const login_form_title = document.getElementById('login-form-title');
	const login_form = document.getElementById('login-form');
	const username_field = document.getElementById('username');
	const password_field= document.getElementById('password');

	const term = new window.Terminal({
		lineHeight: 1.2,
		//fontSize: 14,
		fontFamily: 'Ubuntu Mono, Consolas, SF Mono, courier-new, courier, monospace'
	});
	const fit_addon = new window.FitAddon.FitAddon();
	const text_decoder = new TextDecoder();

	term.loadAddon(fit_addon)
	term.open(terminal_view_container);

	let set_terminal_target = function(name) {
		terminal_target.innerText = name;
		login_form_title.innerText = name
	}

	let set_terminal_status = function(msg, errmsg) {
		if (msg != null) terminal_status.innerText = msg;
		if (errmsg != null) terminal_errmsg.innerText = errmsg
	}

	let adjust_terminal_size_unconnected = function() {
		fit_addon.fit();
	}

	let fetch_session_info = async function() {
		let url = window.location.protocol + '//' + window.location.host;
		url += `/_ssh/server-conns/${conn_id}/routes/${route_id}`;

		try {
			const resp = await fetch(url);
			if (!resp.ok) throw new Error(`HTTP error in getting route(${conn_id},${route_id}) info - status ${resp.status}`);
			const route = await resp.json()
			if ('client-peer-name' in route) {
				set_terminal_target(route['client-peer-name']) // change to the name
				document.title = route['client-peer-name']
			}
		} catch (e) {
			set_terminal_target('');
			document.title = '';
			set_terminal_status (null, e);
		}
	}

	let toggle_login_form = function(visible) {
		if (visible) fetch_session_info();
		login_container.style.visibility = (visible? 'visible': 'hidden');
		terminal_disconnect.style.visibility = (visible? 'hidden': 'visible');
		if (visible) username_field.focus();
		else term.focus();
	}

	toggle_login_form(true);
	window.onresize = adjust_terminal_size_unconnected;
	adjust_terminal_size_unconnected()

	login_form.onsubmit = async function(event) {
		event.preventDefault();
		toggle_login_form(false)

		const username = username_field.value.trim();
		const password = password_field.value.trim();

		let prefix = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
		let url = prefix + window.location.host+ `/_ssh-ws/${conn_id}/${route_id}`;
		const socket = new WebSocket(url)
		socket.binaryType = 'arraybuffer';

		set_terminal_status('Connecting...', '');

		const adjust_terminal_size_connected = function() {
			fit_addon.fit();
			if (socket.readyState == 1) // if open
				socket.send(JSON.stringify({ type: 'size', data: [term.rows.toString(), term.cols.toString()] }));
		};

		socket.onopen = function () {
			socket.send(JSON.stringify({ type: 'open', data: [username, password]}));
		};

		socket.onmessage = function(event) {
			try {
				let event_text;
				event_text = (typeof event.data === 'string')? event.data: text_decoder.decode(new Uint8Array(event.data));
				const msg = JSON.parse(event_text);
				if (msg.type == "iov") {
					for (const data of msg.data) term.write(data);
				} else if (msg.type == "status") {
					if (msg.data.length >= 1) {
						if (msg.data[0] == 'opened') {
							set_terminal_status('Connected', '');
							adjust_terminal_size_connected()
							term.clear()
						} else if (msg.data[0] == 'closed') {
							// doesn't really matter
							// socket.onclose() will be executed anyway
						}
					}
				} else if (msg.type == "error") {
					toggle_login_form(true);
					window.onresize = adjust_terminal_size_unconnected;
					set_terminal_status(null, msg.data.join(' '))
				}
			} catch (e) {
				set_terminal_status('Disconnected', e);
				toggle_login_form(true)
				window.onresize = adjust_terminal_size_unconnected;
			}
		};

		socket.onerror = function(event) {
			set_terminal_status('Disconnected', event);
			toggle_login_form(true)
			window.onresize = adjust_terminal_size_unconnected;
		};

		socket.onclose = function() {
			set_terminal_status('Disconnected', null);
			toggle_login_form(true)
			window.onresize = adjust_terminal_size_unconnected;
		};

		term.onData(function(data) {
			if (socket.readyState == 1) // if open
				socket.send(JSON.stringify({ type: 'iov', data: [data] }));
		});

		window.onresize = adjust_terminal_size_connected;
		terminal_disconnect.onclick = function(event) {
			socket.send(JSON.stringify({ type: 'close', data: [""] }));
			//socket.close()
		};
	}
};
</script>
</head>

<body>

<div id="login-container">
	<div id="login-form-container">
		<div id="login-form-title"></div>
		<form id="login-form">
			<label>
				Username: <input type="text" id="username" required />
			</label>
			<br /><br />
			<label>
				Password: <input type="password" id="password" required />
			</label>
			<br /><br />
			<button type="submit">Connect</button>
		</form>
	</div>
</div>

<div id="terminal-container">
<div id="terminal-info-container">
	<div id="terminal-target"></div>
	<div id="terminal-status"></div>
	<div id="terminal-errmsg"></div>
	<div id="terminal-control">
		<button id="terminal-disconnect" type="button">Disconnect</button>
	</div>
</div>
<div id="terminal-view-container"></div>
</div>
</body>
</html>