function textNode(text) {
	const node = new commonmark.Node('text', undefined);
	node.literal = text;
	return node;
}

function linkNode(text, link) {
	const linkNode = new commonmark.Node('link', undefined);
	if (link.startsWith('#')) {
		linkNode.destination = `#q=${encodeURIComponent(link)}`;
	} else {
		linkNode.destination = link;
	}
	linkNode.appendChild(textNode(text));
	return linkNode;
}

function splitMatches(text, regexp) {
	// Regexp must be sticky.
	regexp = new RegExp(regexp, 'gm');

	let i = 0;
	const result = [];

	let match = regexp.exec(text);
	while (match) {
		const matchText = match[0];

		if (match.index > i) {
			result.push([text.substring(i, match.index), false]);
		}

		result.push([matchText, true]);
		i = match.index + matchText.length;

		match = regexp.exec(text);
	}

	if (i < text.length) {
		result.push([text.substring(i, text.length), false]);
	}

	return result;
}

const regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)');

function split(textNodes) {
	const text = textNodes.map((n) => n.literal).join('');
	const parts = splitMatches(text, regex);

	return parts.map((part) => {
		if (part[1]) {
			return linkNode(part[0], part[0]);
		} else {
			return textNode(part[0]);
		}
	});
}

export function transform(parsed) {
	const walker = parsed.walker();
	let event;

	let nodes = [];
	while ((event = walker.next())) {
		const node = event.node;
		if (event.entering && node.type === 'text') {
			nodes.push(node);
		} else {
			if (nodes.length > 0) {
				split(nodes)
					.reverse()
					.forEach((newNode) => {
						nodes[0].insertAfter(newNode);
					});

				nodes.forEach((n) => n.unlink());
				nodes = [];
			}
		}
	}

	if (nodes.length > 0) {
		split(nodes)
			.reverse()
			.forEach((newNode) => {
				nodes[0].insertAfter(newNode);
			});
		nodes.forEach((n) => n.unlink());
	}

	return parsed;
}