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

import $ from 'jquery';

const classExp = 'toggler--expanded';
const classCol = 'toggler--collapsed';

export function enableCollapsables() {
	enableCollapsable( {
		selector: '.tree li[class*="toggler--"]',
		nodeElement: 'li',
		dontToggleClass: 'tree__item__text',

		collapsedClass: classCol,
		expandedClass: classExp
	} );

	enableCollapsable( {
		selector: '.collapsing-list__term[class*="toggler--"]',
		nodeElement: '.collapsing-list__term',
		dontToggleClass: [ 'collapsing-list__type', 'collapsing-list__dev-names--active' ],

		collapsedClass: classCol,
		expandedClass: classExp
	} );
}

function enableCollapsable( options ) {
	$( options.selector ).on( 'click', function( evt ) {
		const clicked = $( this );
		const target = $( evt.target );
		const parentNode = target.closest( options.nodeElement );

		if ( parentNode.is( options.selector ) ) {
			if ( hasClassFrom( target, 'hidden' ) || hasClassFrom( target.parent(), 'hidden' ) ) {
				return;
			}

			if ( ( target.is( 'a' ) || target.is( 'code' ) ) && hasClassFrom( target, options.dontToggleClass ) ) {
				return;
			}

			clicked.toggleClass( `${ options.expandedClass } ${ options.collapsedClass }` );
			evt.stopPropagation();
		}
	} );

	function hasClassFrom( target, classArray ) {
		let ret = false;
		if ( typeof classArray === 'string' ) {
			return target.hasClass( classArray );
		}
		classArray.forEach( cls => {
			if ( target.hasClass( cls ) ) {
				ret = true;
			}
		} );
		return ret;
	}
}

export function hideTogglers() {
	$( '.collapsing-list__item' ).each( function() {
		const item = $( this );
		const excerpt = item.find( '.collapsing-list__excerpt' );
		const hasExcerpt = excerpt.length > 0;

		if ( hasExcerpt ) {
			hideTogglersWithExcerpts( item );
		} else {
			hideTogglersWithoutExcerpts( item );
		}
	} );
}

function hideTogglersWithoutExcerpts( item ) {
	const hasDescription = item.find( '.collapsing-list__description' ).length > 0;

	// Items without description have no togglers in the first place.
	if ( !hasDescription ) {
		const term = item.children( '.collapsing-list__term' );
		term.addClass( 'collapsing-list__term--no-excerpt' );

		return;
	}

	// Check whether there is any content in the extended description.
	const hasContent = item.find( '.collapsing-list__content' ).text().trim().length > 0;

	// Check whether there is a link to the source code.
	const hasSourceLink = item.find( '.see-source' ).length > 0;

	// If none of the criteria above is met, toggler is not needed and can be hidden away.
	if ( !hasContent && !hasSourceLink ) {
		hideTogglerForItem( item );
	}
}

function hideTogglersWithExcerpts( item ) {
	const isExcerptShort = item.find( '.collapsing-list__excerpt--short' ).length > 0;

	// Short excerpts have no togglers in the first place.
	if ( isExcerptShort ) {
		return;
	}

	// Check whether short description is cut off by an ellipsis due to available space being too narrow.
	const excerptParagraph = item.find( '.collapsing-list__excerpt p' );
	// Some elements have no short description, eg.:
	// api/module_basic-styles_attributecommand-AttributeCommand.html#function-constructor
	const excerptHasEllipsis = !excerptParagraph.length ? false :
		Math.abs( excerptParagraph[ 0 ].clientWidth - excerptParagraph[ 0 ].scrollWidth ) > 0;

	// Check whether there is any content in the extended description.
	const hasContent = item.find( '.collapsing-list__content' ).text().trim().length > 0;

	// Check whether there is a link to the source code.
	const hasSourceLink = item.find( '.see-source' ).length > 0;

	// If none of the criteria above is met, toggler is not needed and can be hidden away.
	if ( !excerptHasEllipsis && !hasContent && !hasSourceLink ) {
		hideTogglerForItem( item );
	}
}

function hideTogglerForItem( item ) {
	const term = item.children( '.collapsing-list__term' );

	term.removeClass( classCol );
	term.addClass( classExp );
	term.addClass( 'hidden' );
}
