import { slugify } from '@gravityforms/utils';
import Icon from '../../elements/Icon';
import Image from '../../elements/Image';

/**
 * @function normalizeText
 * @description Normalizes the provided text and trims leading and trailing spaces.
 *
 * @since 4.5.0
 *
 * @param {string} text The text to normalize.
 *
 * @return {string} The normalized text.
 */
export const normalizeText = ( text = '' ) => {
	return text
		.normalize( 'NFD' )
		.replace( /[\u0300-\u036f]/g, '' )
		.trim();
};

/**
 * @function getId
 * @description Get the id from the prefix and key provided.
 *
 * @since 4.5.0
 *
 * @param {string} prefix The id prefix.
 * @param {string} key    The id key.
 *
 * @return {string} The id.
 */
export const getId = ( prefix, key ) => slugify( `${ prefix }-${ key }` );

/**
 * @function getSearchItem
 * @description Get the search item.
 *
 * @since 4.5.0
 *
 * @param {string} idPrefix The id prefix.
 *
 * @return {object} The search item.
 */
export const getSearchItem = ( idPrefix ) => ( {
	component: 'search',
	id: getId( idPrefix, 'search' ),
} );

/**
 * @function augmentListItems
 * @description Augment list items to add id to the item.
 *
 * @since 4.5.0
 *
 * @param {Array}   listItems      The list items.
 * @param {object}  args           Arguments to augment list items with.
 * @param {boolean} args.hasSearch Whether the dropdown has search or not.
 * @param {string}  args.id        The id prefix.
 *
 * @return {Array} The augmented list items.
 */
export const augmentListItems = ( listItems, { hasSearch = false, id: idPrefix = '' } ) => {
	const newListItems = [
		...listItems,
		...( hasSearch ? [ getSearchItem( idPrefix ) ] : [] ),
	];

	return newListItems.map( ( item ) => {
		if ( item.component === 'search' ) {
			return item;
		}
		return {
			...item,
			id: getId( idPrefix, item.value ),
		};
	} );
};

/**
 * @function getListItemsState
 * @description Gets the state for list items.
 *
 * @since 4.5.0
 *
 * @param {Array}   listItems      The list items.
 * @param {object}  args           Arguments to augment list items with.
 * @param {boolean} args.hasSearch Whether the dropdown has search or not.
 * @param {string}  args.id        The id prefix.
 *
 * @return {object} The list items state.
 */
export const getListItemsState = ( listItems, args = {} ) => {
	const items = augmentListItems( listItems, args );
	return {
		ids: items.map( ( item ) => item.id ),
		items,
	};
};

/**
 * @function filterListItems
 * @description Filters list items based on the search value provided.
 *
 * @since 4.5.0
 *
 * @param {Array}  listItems   The list items.
 * @param {string} searchValue The search value.
 *
 * @return {Array} The filtered list items.
 */
export const filterListItems = ( listItems, searchValue ) => {
	if ( searchValue === '' ) {
		return listItems;
	}

	return listItems.filter( ( item ) => {
		const itemLabel = item.label || '';
		if ( ! itemLabel ) {
			return false;
		}

		return normalizeText( itemLabel ).toLowerCase().indexOf( searchValue.toLowerCase() ) !== -1;
	} );
};

/**
 * @function getComponent
 * @description Gets the component from the args provided.
 *
 * @since 4.5.0
 *
 * @param {object} args The component args.
 *
 * @return {JSX.Element} The component.
 */
export const getComponent = ( args = {} ) => {
	let component = null;

	switch ( args.component ) {
		case 'Icon':
			component = <Icon { ...args.props } />;
			break;
		case 'Image':
			component = <Image { ...args.props } />;
			break;
		default:
			component = null;
	}

	return component;
};
