const markJsUtils = {};

const isInsideContainer = (node, tagName) => {
	if (!node) return false;

	tagName = tagName.toLowerCase();

	while (node) {
		if (node.tagName && node.tagName.toLowerCase() === tagName) return true;
		node = node.parentNode;
	}

	return false;
};

markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
	if (typeof keyword === 'string') {
		keyword = {
			type: 'text',
			value: keyword,
		};
	}

	const isBasicSearch = ['ja', 'zh', 'ko'].indexOf(keyword.scriptType) >= 0;

	let value = keyword.value;

	const getAccuracy = (keyword) => {
		if (isBasicSearch) return 'partially';
		if (keyword.type === 'regex') return 'complementary';
		if (keyword.accuracy) return keyword.accuracy;
		return keyword.value.length >= 2 ? 'partially' : { value: 'exactly', limiters: ':;.,-–—‒_(){}[]!\'"+='.split('') };
	};

	const accuracy = getAccuracy(keyword);

	if (keyword.type === 'regex') {
		// Remove the trailing wildcard and "accuracy = complementary" will take
		// care of highlighting the relevant keywords.

		// Known bug: it will also highlight word that contain the term as a
		// suffix for example for "ent*", it will highlight "present" which is
		// incorrect (it should only highlight what starts with "ent") but for
		// now will do. Mark.js doesn't have an option to tweak this behaviour.
		value = keyword.value.substr(0, keyword.value.length - 1);
	}

	mark.mark(
		[value],
		{

			accuracy: accuracy,
			filter: (node, _term, _totalCounter, _counter) => {
				// We exclude SVG because it creates a "<mark>" tag inside
				// the document, which is not a valid SVG tag. As a result
				// the content within that tag disappears.
				//
				// mark.js has an "exclude" parameter, but it doesn't work
				// so we use "filter" instead.
				//
				// https://github.com/joplin/plugin-abc-sheet-music
				if (isInsideContainer(node, 'SVG')) return false;

				// We exclude joplin-source because it contains the raw source
				// for editable blocks (mermaid diagrams, etc.). If we highlight
				// inside these elements, the <mark> tags corrupt the source code
				// and cause rendering to fail when switching editors.
				//
				// https://github.com/laurent22/joplin/issues/14142
				if (node.parentElement?.closest('.joplin-source')) return false;

				return true;
			},
			...extraOptions,
		},
	);
};

if (typeof module !== 'undefined') {
	module.exports = markJsUtils;
}
