const require_utils_listSpecialChars = require('./listSpecialChars.cjs');

//#region src/utils/reorderParagraphs.ts
/**
* Split a text into paragraphs.
*
* We consider a paragraph boundary to be a block of at least two consecutive
* new-lines that is immediately followed by a non-white-space character.  This
* way, internal blank lines that are part of the same paragraph (e.g. a list
* item that purposely contains a visual break) are preserved while true
* paragraph breaks – the ones generated when calling `arr.join("\n\n")` in
* the tests – are still detected.
*/
const splitByParagraph = (text) => {
	const paragraphs = [];
	const tokens = text.split(/(\n{2,})/);
	for (let i = 0; i < tokens.length; i++) {
		const token = tokens[i];
		if (i % 2 === 0) {
			if (token) paragraphs.push(token);
			continue;
		}
		const pairsOfNewlines = Math.floor(token.length / 2);
		const blankParagraphs = Math.max(0, pairsOfNewlines - 2);
		for (let j = 0; j < blankParagraphs; j++) paragraphs.push("\n\n");
	}
	return paragraphs;
};
/**
* Determine whether two paragraphs match – either exactly, or by sharing the
* same "special-character signature".
*/
const paragraphMatches = (paragraph, baseParagraph, paragraphSignature, baseSignature) => {
	if (paragraph === baseParagraph) return true;
	if (paragraphSignature.length !== baseSignature.length) return false;
	for (let i = 0; i < paragraphSignature.length; i++) if (paragraphSignature[i].char !== baseSignature[i].char) return false;
	return true;
};
/**
* Re-order `textToReorder` so that its paragraphs follow the ordering found in
* `baseFileContent`, while preserving any extra paragraphs (those not present
* in the base file) in a position that is intuitive for a human reader: right
* after the closest preceding paragraph coming from the base file.
*/
const reorderParagraphs = (textToReorder, baseFileContent) => {
	const baseFileParagraphs = splitByParagraph(baseFileContent);
	const textToReorderParagraphs = splitByParagraph(textToReorder);
	const baseSignatures = baseFileParagraphs.map((p) => require_utils_listSpecialChars.listSpecialChars(p));
	const textSignatures = textToReorderParagraphs.map((p) => require_utils_listSpecialChars.listSpecialChars(p));
	const firstMatchIndexForBase = Array(baseFileParagraphs.length).fill(-1);
	const paragraphMatchedBaseIdx = Array(textToReorderParagraphs.length).fill(null);
	for (let i = 0; i < textToReorderParagraphs.length; i++) {
		const paragraph = textToReorderParagraphs[i];
		const sig = textSignatures[i];
		let foundIdx = baseFileParagraphs.findIndex((baseParagraph, idx) => firstMatchIndexForBase[idx] === -1 && paragraph === baseParagraph);
		if (foundIdx === -1) foundIdx = baseFileParagraphs.findIndex((baseParagraph, idx) => firstMatchIndexForBase[idx] === -1 && paragraphMatches(paragraph, baseParagraph, sig, baseSignatures[idx]));
		if (foundIdx !== -1) {
			firstMatchIndexForBase[foundIdx] = i;
			paragraphMatchedBaseIdx[i] = foundIdx;
		}
	}
	const insertAfterBaseIdx = Array(textToReorderParagraphs.length).fill(-1);
	let maxBaseIdxEncountered = -1;
	for (let i = 0; i < textToReorderParagraphs.length; i++) {
		const matchedBase = paragraphMatchedBaseIdx[i];
		if (matchedBase !== null) {
			if (matchedBase > maxBaseIdxEncountered) maxBaseIdxEncountered = matchedBase;
		} else insertAfterBaseIdx[i] = maxBaseIdxEncountered;
	}
	const result = [];
	const extraParagraphsBuckets = {};
	insertAfterBaseIdx.forEach((afterIdx, paragraphIdx) => {
		if (afterIdx === -1) return;
		extraParagraphsBuckets[afterIdx] = extraParagraphsBuckets[afterIdx] || [];
		extraParagraphsBuckets[afterIdx].push(paragraphIdx);
	});
	for (let bIdx = 0; bIdx < baseFileParagraphs.length; bIdx++) {
		const matchedParagraphIdx = firstMatchIndexForBase[bIdx];
		if (matchedParagraphIdx !== -1) result.push(textToReorderParagraphs[matchedParagraphIdx]);
		if (extraParagraphsBuckets[bIdx]) extraParagraphsBuckets[bIdx].forEach((pIdx) => {
			result.push(textToReorderParagraphs[pIdx]);
		});
	}
	const leadingExtras = [];
	insertAfterBaseIdx.forEach((afterIdx, pIdx) => {
		if (afterIdx === -1 && paragraphMatchedBaseIdx[pIdx] === null) leadingExtras.push(textToReorderParagraphs[pIdx]);
	});
	return [...leadingExtras, ...result].join("\n\n");
};

//#endregion
exports.reorderParagraphs = reorderParagraphs;
//# sourceMappingURL=reorderParagraphs.cjs.map