/**
 * External dependencies
 */
import { FormTokenField } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { __ } from '@wordpress/i18n';

/**
 * List of available post formats with labels for selection.
 * Sorted alphabetically for better user experience.
 */
const POST_FORMATS = [
	{ value: 'aside', label: __( 'Aside', 'spectra-pro' ) },
	{ value: 'audio', label: __( 'Audio', 'spectra-pro' ) },
	{ value: 'chat', label: __( 'Chat', 'spectra-pro' ) },
	{ value: 'gallery', label: __( 'Gallery', 'spectra-pro' ) },
	{ value: 'image', label: __( 'Image', 'spectra-pro' ) },
	{ value: 'link', label: __( 'Link', 'spectra-pro' ) },
	{ value: 'quote', label: __( 'Quote', 'spectra-pro' ) },
	{ value: 'standard', label: __( 'Standard', 'spectra-pro' ) },
	{ value: 'status', label: __( 'Status', 'spectra-pro' ) },
	{ value: 'video', label: __( 'Video', 'spectra-pro' ) },
].sort( ( a, b ) => {
	const normalizedA = a.label.toUpperCase();
	const normalizedB = b.label.toUpperCase();

	if ( normalizedA < normalizedB ) {
		return -1;
	}

	if ( normalizedA > normalizedB ) {
		return 1;
	}
	return 0;
} );

/**
 * Converts an array of format labels to their corresponding values.
 *
 * @since x.x.x
 *
 * @param {string[]} names   List of format names (labels).
 * @param {Object[]} formats Available formats with labels and values.
 * @return {string[]} 		 Array of corresponding format values.
 */
const formatNamesToValues = ( names, formats ) => {
	return names
		.map( ( name ) => {
			return formats.find(
				( item ) =>
					item.label.toLocaleLowerCase() === name.toLocaleLowerCase()
			)?.value;
		} )
		.filter( Boolean ); // Filters out undefined values.
};

/**
 * FormatControls component for selecting post formats using a token field.
 *
 * @since x.x.x
 *
 * @param {Object} props Component properties.
 * @return {Element}     The FormatControls component.
 */
const FormatControls = ( props ) => {
	const {
		onChange,
		query: { format },
	} = props;

	// Ensures format is always treated as an array.
	const normalizedFormats = Array.isArray( format ) ? format : [ format ];

	// Fetches supported post formats from the theme.
	const { supportedFormats } = useSelect( ( select ) => {
		const themeSupports = select( coreStore ).getThemeSupports();
		return {
			supportedFormats: themeSupports.formats,
		};
	}, [] );

	// Filters the available post formats based on theme support.
	const formats = POST_FORMATS.filter( ( item ) =>
		supportedFormats.includes( item.value )
	);

	// Retrieves the label of selected format(s).
	const values = normalizedFormats
		.map(
			( name ) => formats.find( ( item ) => item.value === name )?.label
		)
		.filter( Boolean );

	// Provides a list of available formats excluding selected ones.
	const suggestions = formats
		.filter( ( item ) => ! normalizedFormats.includes( item.value ) )
		.map( ( item ) => item.label );

	return (
		<FormTokenField
			label={ __( 'Formats', 'spectra-pro' ) }
			value={ values }
			suggestions={ suggestions }
			onChange={ ( newValues ) => {
				onChange( {
					format: formatNamesToValues( newValues, formats ), // Converts selected labels to format values.
				} );
			} }
			__experimentalShowHowTo={ false }
			__experimentalExpandOnFocus
			__nextHasNoMarginBottom
			__next40pxDefaultSize
		/>
	);
};

export default FormatControls;
