import {
	__experimentalToggleGroupControl as ToggleGroupControl,
	__experimentalToggleGroupControlOption as ToggleGroupControlOption,
	__experimentalToolsPanel as ToolsPanel,
	__experimentalToolsPanelItem as ToolsPanelItem,
	ToggleControl,
	SelectControl as WCSelectControl,
} from '@wordpress/components';
import {
	InspectorControls,
	RichText,
	useBlockProps,
	__experimentalUseBorderProps as useBorderProps,
	__experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
	__experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
} from '@wordpress/block-editor';
import { __, _x } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';

export default function PostNavigationLinkEdit( {
	context: { postType },
	attributes,
	setAttributes,
} ) {
	const { type, label, showTitle, linkLabel, arrow, taxonomy } = attributes;
	const isNext = type === 'next';
	let placeholder = isNext ? __( 'Next' ) : __( 'Previous' );

	const arrowMap = {
		none: '',
		arrow: isNext ? '→' : '←',
		chevron: isNext ? '»' : '«',
	};

	const displayArrow = arrowMap[ arrow ];

	if ( showTitle ) {
		placeholder = isNext
			? /* translators: Label before for next and previous post. There is a space after the colon. */
				__( 'Next: ' ) // eslint-disable-line @wordpress/i18n-no-flanking-whitespace
			: /* translators: Label before for next and previous post. There is a space after the colon. */
				__( 'Previous: ' ); // eslint-disable-line @wordpress/i18n-no-flanking-whitespace
	}

	const ariaLabel = isNext ? __( 'Next post' ) : __( 'Previous post' );

	/*
	 * Border, shadow and spacing serialization is skipped for this block so the
	 * styles are not applied to the empty wrapper the front end renders when
	 * there is no adjacent post. The editor always renders the link, so they
	 * always apply here.
	 */
	const borderProps = useBorderProps( attributes );
	const shadowProps = getShadowClassesAndStyles( attributes );
	const spacingProps = getSpacingClassesAndStyles( attributes );
	const blockProps = useBlockProps( {
		className: borderProps.className,
		style: {
			...borderProps.style,
			...shadowProps.style,
			...spacingProps.style,
		},
	} );
	const taxonomies = useSelect(
		( select ) => {
			const { getTaxonomies } = select( coreStore );
			const filteredTaxonomies = getTaxonomies( {
				type: postType,
				per_page: -1,
			} );
			return filteredTaxonomies;
		},
		[ postType ]
	);
	const getTaxonomyOptions = () => {
		const selectOption = {
			label: __( 'Unfiltered' ),
			value: '',
		};
		const taxonomyOptions = ( taxonomies ?? [] )
			.filter( ( { visibility } ) => !! visibility?.publicly_queryable )
			.map( ( item ) => {
				return {
					value: item.slug,
					label: item.name,
				};
			} );

		return [ selectOption, ...taxonomyOptions ];
	};

	const dropdownMenuProps = useToolsPanelDropdownMenuProps();

	return (
		<>
			<InspectorControls>
				<ToolsPanel
					label={ __( 'Settings' ) }
					resetAll={ () => {
						setAttributes( {
							showTitle: false,
							linkLabel: false,
							arrow: 'none',
						} );
					} }
					dropdownMenuProps={ dropdownMenuProps }
				>
					<ToolsPanelItem
						label={ __( 'Display the title as a link' ) }
						isShownByDefault
						hasValue={ () => showTitle }
						onDeselect={ () =>
							setAttributes( { showTitle: false } )
						}
					>
						<ToggleControl
							label={ __( 'Display the title as a link' ) }
							help={ __(
								'If you have entered a custom label, it will be prepended before the title.'
							) }
							checked={ !! showTitle }
							onChange={ () =>
								setAttributes( {
									showTitle: ! showTitle,
								} )
							}
						/>
					</ToolsPanelItem>
					{ showTitle && (
						<ToolsPanelItem
							label={ __(
								'Include the label as part of the link'
							) }
							isShownByDefault
							hasValue={ () => !! linkLabel }
							onDeselect={ () =>
								setAttributes( { linkLabel: false } )
							}
						>
							<ToggleControl
								label={ __(
									'Include the label as part of the link'
								) }
								checked={ !! linkLabel }
								onChange={ () =>
									setAttributes( {
										linkLabel: ! linkLabel,
									} )
								}
							/>
						</ToolsPanelItem>
					) }
					<ToolsPanelItem
						label={ __( 'Arrow' ) }
						isShownByDefault
						hasValue={ () => arrow !== 'none' }
						onDeselect={ () => setAttributes( { arrow: 'none' } ) }
					>
						<ToggleGroupControl
							label={ __( 'Arrow' ) }
							value={ arrow }
							onChange={ ( value ) => {
								setAttributes( { arrow: value } );
							} }
							help={ __(
								'A decorative arrow for the next and previous link.'
							) }
							isBlock
						>
							<ToggleGroupControlOption
								value="none"
								label={ _x(
									'None',
									'Arrow option for Next/Previous link'
								) }
							/>
							<ToggleGroupControlOption
								value="arrow"
								label={ _x(
									'Arrow',
									'Arrow option for Next/Previous link'
								) }
							/>
							<ToggleGroupControlOption
								value="chevron"
								label={ _x(
									'Chevron',
									'Arrow option for Next/Previous link'
								) }
							/>
						</ToggleGroupControl>
					</ToolsPanelItem>
				</ToolsPanel>
			</InspectorControls>
			<InspectorControls group="advanced">
				<WCSelectControl
					label={ __( 'Filter by taxonomy' ) }
					value={ taxonomy }
					options={ getTaxonomyOptions() }
					onChange={ ( value ) =>
						setAttributes( {
							taxonomy: value,
						} )
					}
					help={ __(
						'Only link to posts that have the same taxonomy terms as the current post. For example the same tags or categories.'
					) }
				/>
			</InspectorControls>
			<div { ...blockProps }>
				{ ! isNext && displayArrow && (
					<span
						className={ `wp-block-post-navigation-link__arrow-previous is-arrow-${ arrow }` }
					>
						{ displayArrow }
					</span>
				) }
				<RichText
					tagName="a"
					identifier="label"
					aria-label={ ariaLabel }
					placeholder={ placeholder }
					value={ label }
					withoutInteractiveFormatting
					onChange={ ( newLabel ) =>
						setAttributes( { label: newLabel } )
					}
				/>
				{ showTitle && (
					<a
						href="#post-navigation-pseudo-link"
						onClick={ ( event ) => event.preventDefault() }
					>
						{ __( 'An example title' ) }
					</a>
				) }
				{ isNext && displayArrow && (
					<span
						className={ `wp-block-post-navigation-link__arrow-next is-arrow-${ arrow }` }
						aria-hidden
					>
						{ displayArrow }
					</span>
				) }
			</div>
		</>
	);
}
