/**
 * @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md.
 */

import Fuse from 'fuse.js';
import $ from 'jquery';

export function setUpFuse() {
	const options = {
		shouldSort: true,
		threshold: 0.35,
		includeScore: true,
		keys: [ 'shortName' ]
	};

	const dataProject = $( '[data-project]' );

	if ( dataProject.length === 0 || $( '.top__menu__api' ).length === 0 ) {
		return;
	}

	const projectSlug = dataProject.attr( 'data-project' );
	const projectPathMatch = new RegExp( `^\\S*/${ projectSlug }/[^/]+` ).exec( window.location.pathname );

	if ( !projectPathMatch ) {
		return;
	}

	const projectPath = projectPathMatch[ 0 ];

	$.ajax( {
		url: `${ projectPath }/api.json`,
		dataType: 'json'
	} )
		.done( data => {
			const fuse = new Fuse( data, options );

			window.apiSearch = query => {
				const searchedQuery = query || $( '#docsearch_input' ).val();

				return fuse.search( searchedQuery )
					.map( match => {
						if ( match.item.kind === 'class' ||
							match.item.kind === 'interface' ||
							match.item.kind === 'typedef' ||
							match.item.kind === 'mixin' ) {
							match.score -= 0.01;
						}

						if ( match.item.priority > 0 ) {
							match.score -= match.item.priority / 500;
						}

						return match;
					} )
					.sort( ( a, b ) => {
						return a.score - b.score;
					} )
					.map( ( match, idx ) => {
						match.index = idx;

						return match;
					} )
					// Display items of same name lower if they are inherited or mixed.
					.sort( ( a, b ) => {
						if ( a.item.name === b.item.name ) {
							if ( a.item.isDerived === b.item.isDerived ) {
								return a.index - b.index;
							} else if ( !a.item.isDerived ) {
								return -1;
							} else {
								return 1;
							}
						} else {
							return a.index - b.index;
						}
					} )
					.map( ( match, idx ) => {
						match.index = idx;

						return match;
					} )
					// Display public items higher.
					.sort( ( a, b ) => {
						if ( a.item.access === b.item.access ) {
							return a.index - b.index;
						} else if ( a.item.access === 'public' ) {
							return -1;
						} else {
							return 1;
						}
					} )
					.slice( 0, 20 )
					// Convert search results to format supported by docsearch.
					.map( match => {
						return {
							url: window.location.origin + projectPath + '/' + match.item.url,
							urlShort: match.item.url,
							hierarchy: {
								lvl0: 'API',
								lvl1: addHighlight( match.item.parent, searchedQuery ),
								lvl2: addHighlight( match.item.preTitle + match.item.name, searchedQuery )
							},
							tags: [ 'api' ],
							fScore: match.score
						};
					} );
			};
		} )
		.fail( () => {
			console.log( 'Local API search not available.' );
		} );
}

function addHighlight( text, searchedQuery ) {
	const highlightClass = 'algolia-docsearch-suggestion--highlight';

	// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions.
	// See: #984.
	const escapedQuery = searchedQuery.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );

	const queryRegex = new RegExp( `(${ escapedQuery })`, 'gi' );

	return text.replace( queryRegex, `<span class="${ highlightClass }">$1</span>` );
}
