async function process_message(whoami, collection, message, kind, parent) {
	let content = JSON.parse(message.content);
	if (typeof content == 'string') {
		let x;
		for (let id of whoami || []) {
			x = await ssb.privateMessageDecrypt(id, content);
			if (x) {
				try {
					content = JSON.parse(x);
					content.draft = true;
					break;
				} catch {
					return;
				}
			}
		}
		if (!x) {
			return;
		}
		if (content.type !== kind || (parent && content.parent !== parent)) {
			return;
		}
	} else {
		content.draft = false;
	}
	if (content?.key) {
		if (content?.tombstone) {
			delete collection[content.key];
		} else {
			collection[content.key] = Object.assign(
				collection[content.key] || {},
				content
			);
		}
	} else {
		collection[message.id] = Object.assign(content, {id: message.id});
		if (!collection[message.id].editors) {
			collection[message.id].editors = [message.author];
		}
	}
	return true;
}

let g_new_message_resolve;
let g_new_message_promise = new Promise(function (resolve, reject) {
	g_new_message_resolve = resolve;
});

function new_message() {
	return g_new_message_promise;
}

ssb.addEventListener('message', function (id) {
	let resolve = g_new_message_resolve;
	g_new_message_promise = new Promise(function (resolve, reject) {
		g_new_message_resolve = resolve;
	});
	if (resolve) {
		resolve();
	}
});

export async function collection(
	ids,
	kind,
	parent,
	max_rowid,
	data,
	include_private
) {
	let whoami = await ssb.getIdentities();
	data = data ?? {};
	let rowid = 0;
	let first = true;
	await ssb.sqlAsync(
		'SELECT MAX(rowid) AS rowid FROM messages',
		[],
		function (row) {
			rowid = row.rowid;
		}
	);
	while (true) {
		if (rowid == max_rowid) {
			await new_message();
			await ssb.sqlAsync(
				'SELECT MAX(rowid) AS rowid FROM messages',
				[],
				function (row) {
					rowid = row.rowid;
				}
			);
			first = false;
		}

		let modified = false;
		let rows = [];
		await ssb.sqlAsync(
			`
				SELECT messages.id, author, json(content) AS content, timestamp
				FROM messages
				JOIN json_each(?1) AS id ON messages.author = id.value
				WHERE
					messages.rowid > ?2 AND
					messages.rowid <= ?3 AND
					((json_extract(messages.content, '$.type') = ?4 AND
					(?5 IS NULL OR json_extract(messages.content, '$.parent') = ?5)) OR
					(?6 AND content LIKE '"%'))
				ORDER BY timestamp
		`,
			[
				JSON.stringify(ids),
				max_rowid ?? -1,
				rowid,
				kind,
				parent,
				include_private ? true : false,
			],
			function (row) {
				rows.push(row);
			}
		);
		max_rowid = rowid;
		for (let row of rows) {
			if (await process_message(whoami, data, row, kind, parent)) {
				modified = true;
			}
		}
		if (first || modified) {
			break;
		}
	}
	return [rowid, data];
}