import * as commonmark from './commonmark.min.js';

function escape(text) {
	return (text ?? '').replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
}

function escapeAttribute(text) {
	return (text ?? '').replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#39;');
}

function markdown(md) {
	let reader = new commonmark.Parser({safe: true});
	let writer = new commonmark.HtmlRenderer();
	let parsed = reader.parse(md || '');
	let walker = parsed.walker();
	let event, node;
	while ((event = walker.next())) {
		node = event.node;
		if (event.entering) {
			if (node.type == 'image') {
				if (node.destination.startsWith('&')) {
					node.destination = '/' + node.destination + '/view';
				}
			}
		}
	}
	return writer.render(parsed);
}

export async function render_blog_post_html(blog_post) {
	let blob = utf8Decode(await ssb.blobGet(blog_post.blog));
	return `<!DOCTYPE html>
		<html>
			<body>
				<div>
					<div><a href="../ssb/#${escapeAttribute(blog_post.author)}">${escape(blog_post.name)}</a> ${escape(new Date(blog_post.timestamp).toString())}</div>
					<div>${markdown(blob)}</div>
				</div>
			</body>
		</html>
	`;
}

function render_blog_post(blog_post) {
	return `
		<div>
			<h2><a href="../ssb/#${escapeAttribute(blog_post.id)}">${escape(blog_post.title)}</a></h2>
			<div><a href="../ssb/#${escapeAttribute(blog_post.author)}">${escape(blog_post.name)}</a> ${escape(new Date(blog_post.timestamp).toString())}</div>
			<div>${markdown(blog_post.summary)}</div>
		</div>
	`;
}

export function render_html(blogs) {
	return `<!DOCTYPE html>
		<html>
			<head>
				<title>🪵Tilde Blog</title>
				<link href="./atom" type="application/atom+xml" rel="alternate" title="🪵Tilde Blog"/>
				<style>
					html {
						background-color: #ccc;
					}
				</style>
				<base target="_blank">
			</head>
			<body>
				<div style="display: flex; flex-direction: row; align-items: center; gap: 1em">
					<h1>🪵Tilde Blog</h1>
					<div style="font-size: xx-small; vertical-align: middle"><a href="/~cory/blog/atom">atom feed</a></div>
				</div>
				${blogs.map(blog_post => render_blog_post(blog_post)).join('\n')}
			</body>
		</html>`;
}

function render_blog_post_atom(blog_post) {
	return `<entry>
		<title>${escape(blog_post.title)}</title>
		<link href="https://tildefriends.net/~cory/ssb/#${blog_post.id}" />
		<id>${blog_post.id}</id>
		<published>${escape(new Date(blog_post.timestamp).toString())}</published>
		<summary>${escape(blog_post.summary)}</summary>
		<author>
			<name>${escape(blog_post.name)}</name>
			<feed>${escape(blog_post.author)}</feed>
		</author>
	</entry>`;
}

export function render_atom(blogs) {
	return `<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>🪵Tilde Blog</title>
	<subtitle>A subtitle.</subtitle>
	<link href="https://tildefriends.net/~cory/blog/atom" rel="self"/>
	<link href="https://tildefriends.net/~cory/blog/"/>
	<id>https://www.tildefriends.net/~cory/blog/</id>
	<updated>${new Date().toString()}</updated>
	${blogs.map(blog_post => render_blog_post_atom(blog_post)).join('\n')}
</feed>`;
}

export async function get_posts() {
	let blogs = [];
	await ssb.sqlAsync(`
		WITH
			blogs AS (
				SELECT
					messages.author,
					messages.id,
					json_extract(messages.content, '$.title') AS title,
					json_extract(messages.content, '$.summary') AS summary,
					json_extract(messages.content, '$.blog') AS blog,
					messages.timestamp
				FROM messages_fts('blog')
				JOIN messages ON messages.rowid = messages_fts.rowid
				WHERE json_extract(messages.content, '$.type') = 'blog'),
			public AS (
				SELECT author FROM (
					SELECT
						messages.author,
						RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
						json_extract(messages.content, '$.publicWebHosting') AS is_public
					FROM messages_fts('about')
					JOIN messages ON messages.rowid = messages_fts.rowid
					WHERE json_extract(messages.content, '$.type') = 'about' AND is_public IS NOT NULL)
				WHERE author_rank = 1 AND is_public),
			names AS (
				SELECT author, name FROM (
					SELECT
						messages.author,
						RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
						json_extract(messages.content, '$.name') AS name
					FROM messages_fts('about')
					JOIN messages ON messages.rowid = messages_fts.rowid
					WHERE json_extract(messages.content, '$.type') = 'about' AND
						json_extract(messages.content, '$.about') = messages.author AND
						name IS NOT NULL)
				WHERE author_rank = 1)
		SELECT blogs.*, names.name FROM blogs
		JOIN public ON public.author = blogs.author
		LEFT OUTER JOIN names ON names.author = blogs.author
		ORDER BY blogs.timestamp DESC LIMIT 20
	`, [], function(row) {
		blogs.push(row);
	});
	return blogs;
}