/* eslint-disable no-jquery/no-jquery-constructor, no-jquery/no-other-methods, no-jquery/no-css,
	no-jquery/no-find-collection, no-jquery/no-each-collection, no-jquery/no-attr */
/**
 * Collapsible tabs for Vector
 */
function init() {
	const cactionsId = 'p-cactions',
		$cactions = $( '#' + cactionsId ),
		// eslint-disable-next-line no-jquery/no-global-selector
		$tabContainer = $( '#p-views ul' );
	let initialCactionsWidth = function () {
		// HACK: This depends on a discouraged feature of jQuery width().
		// The #p-cactions element is generally hidden by default, but
		// the consumers of this function need to know the width that the
		// "More" menu would consume if it were visible. This means it
		// must not return 0 if hidden, but rather virtually render it
		// and compute its width, then hide it again. jQuery width() does
		// all that for us.
		const width = $cactions.width() || 0;
		initialCactionsWidth = function () {
			return width;
		};
		return width;
	};

	// Bind callback functions to animate our drop down menu in and out
	// and then call the collapsibleTabs function on the menu
	$tabContainer
		.on( 'beforeTabCollapse', () => {
			let expandedWidth;
			// If the dropdown was hidden, show it
			if ( !mw.util.isPortletVisible( cactionsId ) ) {
				mw.util.showPortlet( cactionsId );
				// Now that it is visible, force-render it virtually
				// to get its expanded width, then shrink it 1px before we
				// yield from JS (which means the expansion won't be visible).
				// Then animate from the 1px to the expanded width.
				expandedWidth = $cactions.width();
				// eslint-disable-next-line no-jquery/no-animate
				$cactions
					.css( 'width', '1px' )
					.animate( { width: expandedWidth }, 'normal' );
			}
		} )
		.on( 'beforeTabExpand', () => {
			// If we're removing the last child node right now, hide the dropdown
			if ( $cactions.find( 'li' ).length === 1 ) {
				// eslint-disable-next-line no-jquery/no-animate
				$cactions.animate( { width: '1px' }, 'normal', function () {
					$( this ).attr( 'style', '' );
					mw.util.hidePortlet( cactionsId );
				} );
			}
		} )
		.collapsibleTabs( {
			expandCondition: function ( eleWidth ) {
				// This looks a bit awkward because we're doing expensive queries as late
				// as possible.
				const distance = $.collapsibleTabs.calculateTabDistance();
				// If there are at least eleWidth + 1 pixels of free space, expand.
				// We add 1 because .width() will truncate fractional values but .offset() will not.
				if ( distance >= eleWidth + 1 ) {
					return true;
				} else {
					// Maybe we can still expand? Account for the width of the "Actions" dropdown
					// if the expansion would hide it.
					if ( $cactions.find( 'li' ).length === 1 ) {
						return distance >= eleWidth + 1 - initialCactionsWidth();
					} else {
						return false;
					}
				}
			},
			collapseCondition: function () {
				let collapsibleWidth = 0,
					doCollapse = false;

				// This looks a bit awkward because we're doing expensive queries as late
				// as possible.
				// TODO: The dropdown itself should probably "fold" to just the down-arrow
				// (hiding the text) if it can't fit on the line?

				// Never collapse if there is no overlap.
				if ( $.collapsibleTabs.calculateTabDistance() >= 0 ) {
					return false;
				}

				// Always collapse if the "More" button is already shown.
				if ( mw.util.isPortletVisible( cactionsId ) ) {
					return true;
				}

				// If we reach here, this means:
				// 1. #p-cactions is currently empty and invisible (e.g. when logged out),
				// 2. and, there is at least one li.collapsible link in #p-views, as asserted
				//    by handleResize() before calling here. Such link exists e.g. as
				//    "View history" on articles, but generally not on special pages.
				// 3. and, the left-navigation and right-navigation are overlapping
				//    each other, e.g. when making the window very narrow, or if a gadget
				//    added a lot of tabs.
				$tabContainer.children( 'li.collapsible' ).each( ( _index, element ) => {
					collapsibleWidth += $( element ).width() || 0;
					if ( collapsibleWidth > initialCactionsWidth() ) {
						// We've found one or more collapsible links that are wider
						// than the "More" menu would be if it were made visible,
						// which means it is worth doing a collapsing.
						doCollapse = true;
						// Stop this possibly expensive loop the moment the condition is met once.
						return false;
					}
					return;
				} );
				return doCollapse;
			}
		} );
}

module.exports = Object.freeze( { init: init } );
