import React, { useRef } from 'react';
import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components';
import GFSVG from '../icons/GFSVG';
import { withSelect } from '@wordpress/data';
import { FormMergeTags, GPEBState } from '../../stores/gpeb';
import { __ } from '@wordpress/i18n';

const insertMergeTag = (
	mergeTag,
	menuItemNode: React.MutableRefObject< Element >
) => {
	const selection = menuItemNode.current.ownerDocument.getSelection();
	const range = selection.rangeCount ? selection.getRangeAt( 0 ) : null;

	if ( ! range ) {
		// eslint-disable-next-line no-console
		console.error(
			'Unable to add merge tag. window.getSelection() may not be available.'
		);
		return;
	}

	/**
	 * If the start offset and end offset are the same, there isn't any select text to replace.
	 * We're inserting/appending.
	 */
	if ( range.startOffset !== range.endOffset ) {
		range.deleteContents();
	}

	range.insertNode( document.createTextNode( mergeTag ) );

	document.getSelection().focusNode.dispatchEvent( new Event( 'input' ) );
};

function MergeTagSelector( {
	mergeTags,
}: {
	formId: number;
	mergeTags: FormMergeTags;
} ): JSX.Element | undefined {
	const menuItemRef = useRef< Element >( null );

	if ( ! mergeTags ) {
		return undefined;
	}

	return (
		<DropdownMenu icon={ GFSVG } label={ __( 'Select a merge tag to insert', 'gp-entry-blocks' ) }>
			{ ( { onClose } ) => (
				<>
					{ Object.values( mergeTags ).map(
						( group: {
							label: string;
							tags: { tag: string; label: string }[];
						} ) => (
							<MenuGroup
								key={ group.label }
								label={ group.label }
							>
								{ group.tags.map( ( mergeTag ) => (
									<MenuItem
										key={ mergeTag.tag }
										icon={ false }
										ref={ menuItemRef }
										onClick={ () => {
											insertMergeTag(
												mergeTag.tag,
												menuItemRef
											);

											onClose();
										} }
									>
										{ mergeTag.label }
									</MenuItem>
								) ) }
							</MenuGroup>
						)
					) }
				</>
			) }
		</DropdownMenu>
	);
}

export default withSelect<
	{ formMergeTags: GPEBState[ 'formMergeTags' ] },
	{ formId: number }
>( ( select, ownProps ) => {
	return {
		mergeTags: select( 'gp-entry-blocks' ).getFormMergeTags(
			ownProps.formId
		),
	};
} )( MergeTagSelector );
