import {structuredPatch} from './jsdiff.js';

function decode(text) {
	return text.replaceAll(/%[A-Za-z0-9]{2}/g, function (match) {
		return String.fromCharCode(parseInt(match.substring(1), 16));
	});
}

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

async function render_file(left, right, file) {
	if (left.files[file] && !right.files[file]) {
		return `<h2>${file} <span style="font-size: small">Deleted</span></h2>`;
	} else if (!left.files[file] && right.files[file]) {
		return `<h2>${file} <span style="font-size: small">Added</span></h2>`;
	} else if (left.files[file] != right.files[file]) {
		let left_blob = utf8Decode(await ssb.blobGet(left.files[file]));
		let right_blob = utf8Decode(await ssb.blobGet(right.files[file]));
		if (left_blob && right_blob) {
			let patch = structuredPatch(
				`${file} (old)`,
				`${file} (new)`,
				left_blob,
				right_blob
			);
			return `
				<h2>${file} <span style="font-size: small">Modified</span></h2>
				${patch.hunks
					.map(function (hunk) {
						return `
						<pre style="padding: 0; margin: 0; background: #000; color: #fff">@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@</pre>
						<pre style="margin-top: 0; background: #fff; border: 1px solid black">${hunk.lines
							.map(function (line) {
								if (line.startsWith('+')) {
									return `<span style="color: #080">${escape(line)}</span>`;
								} else if (line.startsWith('-')) {
									return `<span style="color: #800">${escape(line)}</span>`;
								} else {
									return escape(line);
								}
							})
							.join('\n')}</pre>
					`;
					})
					.join('\n')}
			`;
		} else {
			return `
				<h2>${file} <span style="font-size: small">Modified</span></h2>
				${left_blob ? '' : `old revison missing`}
				${right_blob ? '' : `new revison missing`}
			`;
		}
	} else {
		return `<h2>${file} <span style="font-size: small">Unmodified</span></h2>`;
	}
}

async function main() {
	await app.setDocument('<h1 style="color: #fff">Loading...</h1>');
	try {
		let hash = await app.getHash();
		hash = hash?.startsWith('#') ? hash.substring(1) : hash;
		let parts = hash?.split(':');
		parts = parts.map(decode);
		let left = JSON.parse(utf8Decode(await ssb.blobGet(parts[0])));
		let right = JSON.parse(utf8Decode(await ssb.blobGet(parts[1])));
		let files = [
			...new Set([...Object.keys(left?.files), ...Object.keys(right?.files)]),
		];
		let doc = (
			await Promise.all(files.map((x) => render_file(left, right, x)))
		).join('\n');
		await app.setDocument(`<html style="background-color: #ddd">${doc}</html>`);
	} catch (e) {
		await app.setDocument(
			`<pre style="font-size: x-large; color: #f00; background-color: #fff">${e}\n${e.stack}</pre>`
		);
	}
}

main();
