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

'use strict';

/**
 * A helper function used for searching for a proper doclet structure when creating a link
 * from a guide or an API page.
 *
 * The main goal of this function is to avoid editing the same logic in many places.
 *
 * @param {DataCollection} docletCollection
 * @param {Object} options
 * @param {String} [options.module]
 * @param {String} [options.structure]
 * @param {String} options.member
 * @param {String} [options.label]
 * @param {Object} [options.query={}]
 * @param {Boolean} [options.query.skipModule=false]
 * @param {Boolean} [options.query.memberOnly=false]
 * @returns {Object|null}
 */
module.exports = function findTargetDoclet( docletCollection, options ) {
	const { module, structure, member, label, query } = options;
	const { skipModule, memberOnly } = ( query || {} );

	if ( !structure ) {
		return null;
	}

	// Try to find an instance member...
	let collection = docletCollection.get( `ln:${ structure }#${ member }` );

	// ...or a static member.
	if ( collection.isEmpty ) {
		collection = docletCollection.get( `ln:${ structure }.${ member }` );
	}

	// When the advanced search is enabled, try to find also...
	if ( !memberOnly ) {
		// ...a definition within the same module.
		if ( collection.isEmpty ) {
			collection = docletCollection.get( `ln:${ structure }~${ member }` );
		}

		// To save a backward compatibility, let's try to find a structure without defining a member.
		if ( collection.isEmpty && structure.endsWith( '~' + member ) ) {
			collection = docletCollection.get( `ln:${ structure }` );
		}

		// Then, search for an event declaration (`...~Classname#event:eventName`).
		if ( collection.isEmpty && member === 'event' ) {
			collection = docletCollection.get( `ln:${ structure }#${ member }:${ label }` );
		}

		// (`...~Classname#eventName`). CKEditor 4 / JSDuck.
		if ( collection.isEmpty && member === 'event' ) {
			collection = docletCollection.get( `ln:${ structure }#${ label }` );
		}

		// Search for a module definition only if requested.
		if ( !skipModule && collection.isEmpty ) {
			collection = docletCollection.get( `ln:${ module }` );
		}
	}

	if ( collection.isEmpty ) {
		const typedefCollection = collection = docletCollection.get( `ln:${ structure }` );

		if ( typedefCollection.isEmpty ) {
			return null;
		}

		const typedefItem = typedefCollection.getFirst();

		if ( typedefItem.kind !== 'typedef' ) {
			return null;
		}

		const { properties } = typedefItem;

		return ( properties || [] ).find( item => item.name === member ) ? typedefItem : null;
	}

	let targetDoclet;

	if ( label && collection.size > 1 ) {
		targetDoclet = collection.getByLabel( label );
	}

	if ( !targetDoclet ) {
		targetDoclet = collection.getFirst();
	}

	return targetDoclet;
};
