/**
 * External dependencies.
 */
import { InspectorControls, useSettings } from '@wordpress/block-editor';
import {
	__experimentalToolsPanel as ToolsPanel,
	__experimentalToolsPanelItem as ToolsPanelItem,
	__experimentalUnitControl as UnitControl,
	__experimentalUseCustomUnits as useCustomUnits,
	__experimentalToggleGroupControl as ToggleGroupControl,
	__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import { memo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
 * Internal dependencies.
 */
import InspectorColor from '@spectra-components/inspector-color';

/**
 * Element Sub-settings: Settings that are injected into Core's Dimensions panel.
 *
 * @param {Object} props The element props.
 * @since x.x.x
 * @return {Element} The rendered block settings.
 */
const DimensionsSettings = memo( ( props ) => {
	// Destructure the required props.
	const {
		clientId,
		setAttributes,
		attributes: { checkboxSize, itemsGap, labelCheckboxGap },
	} = props;

	// Fetch available spacing units from editor settings, with fallback.
	const [ availableUnits ] = useSettings( 'spacing.units' ) || [];
	const units = useCustomUnits( {
		availableUnits: availableUnits.length
			? availableUnits
			: [ 'px', '%', 'vw', 'em', 'rem' ],
	} );

	return (
		<InspectorControls group="dimensions">
			{ /* This ToolsPanelItem will reset when the following condition is met:
				- The "checkboxSize" attribute is set to undefined. Default: undefined.
			*/ }
			<ToolsPanelItem
				hasValue={ () => !! checkboxSize }
				label={ __( 'Checkbox Size', 'spectra-pro' ) }
				onDeselect={ () =>
					setAttributes( { checkboxSize: undefined } )
				}
				resetAllFilter={ () => ( {
					checkboxSize: undefined,
				} ) }
				isShownByDefault
				panelId={ clientId }
			>
				<UnitControl
					__next40pxDefaultSize
					label={ __( 'Checkbox Size', 'spectra-pro' ) }
					labelPosition="top"
					value={ checkboxSize }
					min={ 0 }
					onChange={ ( value ) =>
						setAttributes( { checkboxSize: value } )
					}
					units={ units }
				/>
			</ToolsPanelItem>
			{ /* This ToolsPanelItem will reset when the following condition is met:
				- The "itemsGap" attribute is set to undefined. Default: undefined.
			*/ }
			<ToolsPanelItem
				hasValue={ () => !! itemsGap }
				label={ __( 'items Gap', 'spectra-pro' ) }
				onDeselect={ () => setAttributes( { itemsGap: undefined } ) }
				resetAllFilter={ () => ( {
					itemsGap: undefined,
				} ) }
				isShownByDefault
				panelId={ clientId }
			>
				<UnitControl
					__next40pxDefaultSize
					label={ __( 'Items Gap', 'spectra-pro' ) }
					labelPosition="top"
					value={ itemsGap }
					min={ 0 }
					onChange={ ( value ) =>
						setAttributes( { itemsGap: value } )
					}
					units={ units }
				/>
			</ToolsPanelItem>
			{ /* This ToolsPanelItem will reset when the following condition is met:
				- The "labelCheckboxGap" attribute is set to undefined. Default: undefined.
			*/ }
			<ToolsPanelItem
				hasValue={ () => !! labelCheckboxGap }
				label={ __( 'Label-Checkbox Gap', 'spectra-pro' ) }
				onDeselect={ () =>
					setAttributes( { labelCheckboxGap: undefined } )
				}
				resetAllFilter={ () => ( {
					labelCheckboxGap: undefined,
				} ) }
				isShownByDefault
				panelId={ clientId }
			>
				<UnitControl
					__next40pxDefaultSize
					label={ __( 'Label-Checkbox Gap', 'spectra-pro' ) }
					labelPosition="top"
					value={ labelCheckboxGap }
					min={ 0 }
					onChange={ ( value ) =>
						setAttributes( { labelCheckboxGap: value } )
					}
					units={ units }
				/>
			</ToolsPanelItem>
		</InspectorControls>
	);
} );

/**
 * The color settings.
 *
 * @since x.x.x
 *
 * @param {Object} props The element props.
 * @return {Element} The rendered settings.
 */
const ColorSettings = memo( ( props ) => {
	const {
		clientId,
		setAttributes,
		attributes: {
			textColorHover,
			backgroundColorHover,
			backgroundGradientHover,
		},
	} = props;

	return (
		<InspectorColor
			settings={ [
				{
					colorValue: textColorHover,
					label: __( 'Text Hover', 'spectra-pro' ),
					onColorChange: ( value ) =>
						setAttributes( { textColorHover: value } ),
					resetAllFilter: () =>
						setAttributes( { textColorHover: undefined } ),
				},
				{
					colorValue: backgroundColorHover,
					gradientValue: backgroundGradientHover,
					label: __( 'Background Hover', 'spectra-pro' ),
					onColorChange: ( value ) =>
						setAttributes( { backgroundColorHover: value } ),
					onGradientChange: ( value ) =>
						setAttributes( { backgroundGradientHover: value } ),
					resetAllFilter: () =>
						setAttributes( {
							backgroundColorHover: undefined,
							backgroundGradientHover: undefined,
						} ),
				},
			] }
			panelId={ clientId }
		/>
	);
} );

/**
 * Layout Sub-settings: Settings for layout configuration.
 *
 * @param {Object} props The element props.
 * @since x.x.x
 * @return {Element} The rendered block settings.
 */
const LayoutSettings = memo( ( props ) => {
	// Destructure the required props.
	const {
		clientId,
		setAttributes,
		attributes: { layoutType },
	} = props;

	return (
		<InspectorControls group="settings">
			<ToolsPanel
				label={ __( 'General', 'spectra-pro' ) }
				resetAll={ () => setAttributes( { layoutType: 'stack' } ) }
				panelId={ clientId }
			>
				<ToolsPanelItem
					hasValue={ () => layoutType !== 'stack' }
					label={ __( 'Layout', 'spectra-pro' ) }
					onDeselect={ () =>
						setAttributes( { layoutType: 'stack' } )
					}
					resetAllFilter={ () => ( {
						layoutType: 'stack',
					} ) }
					isShownByDefault
					panelId={ clientId }
				>
					<ToggleGroupControl
						label={ __( 'Layout', 'spectra-pro' ) }
						value={ layoutType }
						onChange={ ( value ) =>
							setAttributes( { layoutType: value } )
						}
						isBlock
					>
						<ToggleGroupControlOption
							value="stack"
							label={ __( 'Stack', 'spectra-pro' ) }
						/>
						<ToggleGroupControlOption
							value="inline"
							label={ __( 'Inline', 'spectra-pro' ) }
						/>
					</ToggleGroupControl>
				</ToolsPanelItem>
			</ToolsPanel>
		</InspectorControls>
	);
} );

/**
 * The Editor settings.
 *
 * @param {Object} props The element props.
 * @since x.x.x
 * @return {Element} The rendered settings.
 */
const Settings = ( props ) => (
	<>
		<LayoutSettings { ...{ ...props } } />
		<ColorSettings { ...{ ...props } } />
		<DimensionsSettings { ...{ ...props } } />
	</>
);

export default memo( Settings );
