{% extends "base.html" %}

{% block title %}Container {{container_name}}{% endblock %}

{% block content %}
<main>
	<header>
		<h1>Container <span class="container-name">{{container_name}}</span> {% match info.stack() %}{% when
			Some
			with (stack) %}(<a class="stack-name" href="/stack/{{stack}}/">{{stack}}</a>)
			{% when None %}{% endmatch %}</h1>
		<div class="actions">
			<form action="./start" method="POST"><button type="submit">Start</button></form>
			<form action="./restart" method="POST"><button type="submit">Restart</button></form>
			<form action="./stop" method="POST"><button type="submit">Stop</button></form>
			<form action="./kill" method="POST"><button type="submit">Kill</button></form>
			<form action="./remove" method="POST"><button type="submit">Delete</button></form>
		</div>
	</header>
	<section class="status-section">
		<h2>Status</h2>
		<article>
			<dl class="table">
				<dt>ID</dt>
				<dd>{{ info.id }}</dd>
				<dt>Status</dt>
				<dd data-state="{{ info.state }}">{{ info.state }}</dd>
				<dt>Image</dt>
				<dd>{{ info.image }}</dd>
				<dt>Image ID</dt>
				<dd>{{ info.image_id }}</dd>
				<dt>Created at</dt>
				<dd>{{ info.created_at }}</dd>
			</dl>
			<dl class="list">
				{% match info.volumes %}
				{% when Some with (volumes) %}
				<dt>Volumes</dt>
				{% for volume in volumes %}
				<dd>
					{{ volume.source.clone().unwrap_or_default() }} → {{
					volume.destination.clone().unwrap_or_default() }}
				</dd>
				{% endfor %}
				{% when None %}
				{% endmatch %}
				{% match info.env %}
				{% when Some with (env) %}
				<dt>Environment</dt>
				{% for var in env %}
				<dd>{{ var }}</dd>
				{% endfor %}
				{% when None %}
				{% endmatch %}
				{% match info.labels %}
				{% when Some with (labels) %}
				<dt>Labels</dt>
				{% for label in labels %}
				<dd class="label"><span class="key">{{ label.0 }}</span> = <span class="value">{{
						label.1
						}}</span></dd>
				{% endfor %}
				{% when None %}
				{% endmatch %}
			</dl>
		</article>
	</section>
	<section class="log-section">
		<h2>Logs</h2>
		<code id="log"></code>
	</section>
</main>

<style scoped>
	a.stack-name {
		text-decoration: none;
	}

	main {
		display: flex;
		flex-direction: column;
		gap: 1rem;
	}

	h2 {
		text-transform: uppercase;
		margin: 0;
		padding: 0;
		margin-bottom: 1rem;
	}

	pre {
		margin: 0;
		padding: 0;
	}

	.container-name {
		color: #E796F3;
	}

	.label {

		& .key {
			color: #E796F3;
		}
	}

	#log {
		background-color: var(--bg-raised);
		display: flex;

		display: block;
		max-height: 80vh;
		overflow-y: auto;

		& .error {
			padding: 4px 8px;
			background-color: #3B1219;
			color: #FF9592;
		}

		& p {
			padding: 4px 8px;
			margin: 0;
			background-color: #1a1c38;

			&:nth-child(odd) {
				background-color: #212345;
			}
		}

		& time {
			padding-right: 1ch;
			color: #B1A9FF;
		}
	}

	dd~dt,
	dd~dd {
		border-top: 1px solid #262A65;
	}

	dd[data-state] {
		background-color: #202248;
	}

	dd[data-state="running"] {
		background-color: #113B29;
		color: #3DD68C;
	}

	dd[data-state="stopped"],
	dd[data-state="exited"],
	dd[data-state="dead"] {
		background-color: #500F1C;
		color: #FF9592;
	}

	dt,
	dd {
		box-sizing: border-box;
		padding: 4px;
	}


	dt {
		padding-bottom: 0;
	}

	dd {
		background-color: #171625;
		padding: 4px 8px;
		word-break: break-all;
	}

	dl.table {
		border: 1px solid #3D3E82;
		background-color: #202248;
		margin: 0;

		& dt {
			float: left;
			width: 25%;
		}

		& dd {
			margin-left: 25%;
			border-left: 1px dotted #3D3E82;
		}


		& dd:after {
			content: "";
			display: block;
			clear: both;
		}
	}

	dl.list {
		border: 1px solid #3D3E82;
		background-color: #202248;
		margin: 0;
		border-top: 0;

		& dd {
			margin: 0;
		}

		& dt {
			padding: 4px 8px;
		}
	}


	main>header {
		grid-area: head;
	}

	.status-section {
		grid-area: info;
	}

	.log-section {
		grid-area: log;
	}

	@media (min-width: 1000px) {
		main {
			overflow: hidden;
			display: grid;
			grid-template-areas:
				"head head"
				"info log";

			grid-template-rows: 120px 1fr;
			grid-template-columns: 30vw 1fr;
		}


		.status-section>article,
		#log {
			height: calc(100vh - 240px);
			max-height: none;
			overflow: auto;
		}
	}

	.actions {
		display: flex;
		gap: 0.5rem;

		& form {
			display: flex;
			min-width: 80px;
		}

		& button {
			flex: 1;
		}
	}
</style>

<script type="module">
	import ansiFmt from 'https://esm.run/ansi-to-html';
	const convert = new ansiFmt({
		fg: '#E0DFFE',
		bg: '#171625',
		newline: false,
		escapeXML: true,
		stream: false,
		colors: ["#282c34", "#abb2bf", "#e06c75", "#be5046", "#98c379", "#d19a66", "#61afef", "#c678dd", "#56b6c2", "#4b5263", "#5c6370"]
	});

	const logEl = document.querySelector("#log");
	const logSource = new EventSource(`${location.origin}${location.pathname}log`);
	logSource.addEventListener("error", (ev) => {
		logSource.close();
		const err = document.createElement("div");
		err.className = "error";
		err.appendChild(document.createTextNode("No logs available after this (container not running)"));
		logEl.appendChild(err);
		err.scrollIntoView();
		return;
	});
	logSource.addEventListener("message", (ev) => {
		const data = JSON.parse(ev.data);
		// If an error is received stop listening
		if ("error" in data) {
			logSource.close();
			const err = document.createElement("div");
			err.className = "error";
			err.appendChild(document.createTextNode(data.error));
			logEl.appendChild(err);
			err.scrollIntoView();
			return;
		}
		// Received lines of log
		if ("lines" in data) {
			data.lines.split("\n").forEach(line => {
				if (!line) {
					return;
				}
				// Extract timestamp
				const firstSpace = line.indexOf(' ')
				const [timestamp, logline] = [line.substring(0, firstSpace), line.substring(firstSpace + 1)];
				const lineEl = document.createElement("p");
				lineEl.innerHTML = `<time datetime="${timestamp}">${timestamp}</time>${convert.toHtml(logline)}`.trim();
				logEl.appendChild(lineEl);
				lineEl.scrollIntoView();
			});
		}
	});

	// Fix copying from log (remove double newlines)
	logEl.addEventListener("copy", (event) => {
		const selection = document.getSelection();
		event.clipboardData.setData("text/plain", selection.toString().replace(/\n\n/g, '\n'));
		event.preventDefault();
	});
</script>

{% endblock %}