/**
 * Fetches information about the applications
 * @param apps Record<appName, blobId>
 * @returns an object including the apps' name, emoji, and blobs ids
 */
async function fetch_info(apps) {
	let result = {};

	// For each app
	for (let [key, value] of Object.entries(apps)) {
		// Get it's blob and parse it
		let blob = await ssb.blobGet(value);
		blob = blob ? utf8Decode(blob) : '{}';

		// Add it to the result object
		result[key] = JSON.parse(blob);
	}

	return result;
}

/**
 *
 *
 */
async function fetch_shared_apps() {
	let messages = {};

	await ssb.sqlAsync(
		`
				SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
				FROM messages_fts('"application/tildefriends"')
				JOIN messages ON messages.rowid = messages_fts.rowid
				ORDER BY messages.timestamp
		`,
		[],
		function (row) {
			let content = JSON.parse(row.content);
			for (let mention of content.mentions) {
				if (mention?.type === 'application/tildefriends') {
					messages[JSON.stringify([row.author, mention.name])] = {
						message: row,
						blob: mention.link,
						name: mention.name,
					};
				}
			}
		}
	);

	let result = {};
	for (let app of Object.values(messages).sort(
		(x, y) => y.message.timestamp - x.message.timestamp
	)) {
		let app_object = JSON.parse(utf8Decode(await ssb.blobGet(app.blob)));
		if (app_object) {
			app_object.blob_id = app.blob;
			result[app.name] = app_object;
		}
	}
	return result;
}

async function main() {
	const apps = await fetch_info(await core.apps());
	const core_apps = await fetch_info(await core.apps('core'));
	const shared_apps = await fetch_shared_apps();

	const stylesheet = `
		body {
			color: whitesmoke;
			font-family: sans-serif;
			margin: 16px;
		}
		.container {
			display: grid;
			grid-template-columns: repeat(auto-fill, 64px);
			gap: 1em;
			justify-content: space-around;
			background-color: #ffffff10;
			border: 2px solid #073642;
			border-radius: 8px;
		}

		.app {
			height: 96px;
			width: 64px;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			white-space: nowrap;
		}
		.app > a {
			text-decoration: none;
			max-width: 64px;
			text-overflow: ellipsis ellipsis;
			overflow: hidden;
			color: whitesmoke;
		}
	`;

	const body = `
		<h1 style="text-shadow: #808080 0 0 10px;">Welcome to Tilde Friends.</h1>

		<h2>your apps</h2>
		<div id="apps" class="container"></div>

		<h2>shared apps</h2>
		<div id="shared_apps" class="container"></div>

		<h2>core apps</h2>
		<div id="core_apps" class="container"></div>
	`;

	const script = `
		/*
		 * Creates a list of apps
		 * @param id the id of the element to populate
		 * @param name (a username, 'core' or undefined)
		 * @param apps Object, a list of apps
		 */
		function populate_apps(id, name, apps) {
			// Our target
			var list = document.getElementById(id);

			// For each app in the provided list
			for (let app of Object.keys(apps).sort()) {

				// Create the item
				let div = list.appendChild(document.createElement('div'));
				div.classList.add('app');

				// The app's icon
				let href = name ? '/~' + name + '/' + app + '/' : ('/' + apps[app].blob_id + '/');
				let icon_a = document.createElement('a');
				let icon = document.createElement('div');
				icon.appendChild(document.createTextNode(apps[app].emoji || '📦'));
				icon.style.fontSize = 'xxx-large';
				icon_a.appendChild(icon);
				icon_a.href = href;
				icon_a.target = '_top';
				div.appendChild(icon_a);

				// The app's name
				let a = document.createElement('a');
				a.appendChild(document.createTextNode(app));
				a.href = href;
				a.target = '_top';
				div.appendChild(a);
			}
		}

		populate_apps('apps', '${core.user.credentials?.session?.name}', ${JSON.stringify(apps)});
		populate_apps('core_apps', 'core', ${JSON.stringify(core_apps)});
		populate_apps('shared_apps', undefined, ${JSON.stringify(shared_apps)});
	`;

	// Build the document
	const document = `
	<!DOCTYPE html>
	<html>
		<head>
			<style>
				${stylesheet}
			</style>
		</head>

		<body>
			${body}
		</body>

		<script>
			${script}
		</script>
	</html>`;

	// Send it to the browser
	app.setDocument(document);
}

main();
