import { React, PropTypes, classnames } from '@gravityforms/libraries';
import { useIdContext, useStoreContext } from '@gravityforms/react-utils';
import {
	getId,
	getSearchItem,
} from './utils';
import Input from '../../elements/Input';

const { forwardRef } = React;

/**
 * @module DropdownSearch
 * @description The search component for the dropdown.
 *
 * @since 4.5.0
 *
 * @param {object}              props                  The component props.
 * @param {boolean}             props.ajaxSearch       Whether to use ajax search for the dropdown.
 * @param {boolean}             props.hasSearch        Whether the dropdown has a search component.
 * @param {Function}            props.onSearch         Callback for when the search value changes.
 * @param {object}              props.searchAttributes The search component attributes.
 * @param {string|Array|object} props.searchClasses    The search component classes.
 * @param {object}              ref                    The ref object.
 *
 * @return {JSX.Element} The dropdown search component.
 */
const DropdownSearch = forwardRef( ( {
	ajaxSearch = false,
	hasSearch = false,
	onSearch = () => {},
	searchAttributes = {},
	searchClasses = [],
}, ref ) => {
	const id = useIdContext();
	const dropdownOpen = useStoreContext( ( state ) => state.dropdownOpen );
	const activeItem = useStoreContext( ( state ) => state.activeItem );
	const searchValue = useStoreContext( ( state ) => state.searchValue );
	const setActiveItem = useStoreContext( ( state ) => state.setActiveItem );
	const setSearchValue = useStoreContext( ( state ) => state.setSearchValue );

	if ( ! hasSearch ) {
		return null;
	}

	const listId = getId( id, 'list' );
	const searchId = getId( id, 'search' );

	const {
		customAttributes: searchCustomAttributes = {},
		wrapperClasses: searchWrapperClasses = [],
		...restSearchAttributes
	} = searchAttributes;

	const searchProps = {
		customClasses: classnames( [
			'gform-dropdown__search',
		], searchClasses ),
		...restSearchAttributes,
		controlled: true,
		customAttributes: {
			...searchCustomAttributes,
			autoComplete: 'off',
			role: 'combobox',
			'aria-autocomplete': 'list',
			'aria-haspopup': 'listbox',
			'aria-controls': listId,
			'aria-expanded': dropdownOpen ? 'true' : 'false',
			onMouseMove: () => {
				setActiveItem( getSearchItem( id ) );
			},
			ref,
		},
		id: searchId,
		wrapperClasses: classnames( [
			'gform-dropdown__search-wrapper',
		], searchWrapperClasses ),
		onChange: ( value ) => {
			setSearchValue( value );
			if ( ajaxSearch ) {
				onSearch?.( value );
			}
		},
		value: searchValue,
	};

	if ( activeItem.type === 'search' ) {
		searchProps.customAttributes[ 'data-active-item' ] = 'true';
	} else {
		searchProps.customAttributes[ 'aria-activedescendant' ] = activeItem.id;
	}

	return <Input { ...searchProps } />;
} );

DropdownSearch.propTypes = {
	ajaxSearch: PropTypes.bool,
	hasSearch: PropTypes.bool,
	onSearch: PropTypes.func,
	searchAttributes: PropTypes.object,
	searchClasses: PropTypes.oneOfType( [
		PropTypes.array,
		PropTypes.object,
		PropTypes.string,
	] ),
};

export default DropdownSearch;
