import * as React from 'react'
import {__, _x, sprintf} from '@wordpress/i18n'

import {
	useContext,
	useState,
	useMemo,
	useCallback,
} from '@wordpress/element'

import {
	__experimentalVStack as VStack,
	__experimentalNavigatorBackButton as NavigatorBackButton,
	__experimentalUseNavigator as useNavigator,
	MenuGroup,
	MenuItem,
	Slot,
} from '@wordpress/components'

import {
	chevronLeft,
	trash as trashIcon,
} from '@wordpress/icons'

import {
	ActionInput,
	JsonView,
} from '@ska/components'

import {
	sanitizeURIComponent,
} from '@ska/utils'

import {
	SelectorNav,
} from '.'

import SkaBlocks from '../../../SkaBlocks'

import {
	usePluginPreference,
} from '../../../store'

import {
	sanitizeVariant,
} from '../../../tailwind/attributes'

import {
	useSkaBlocksDispatch,
} from '../../../tailwind/reducer'

import {
	Panel,
	PanelHeader,
	PanelBody,
	CopyItem,
	ResetItem,
	CopyValueItem,
	CopySelectorItem,
	Search,
	InspectorControlsContext,
	FeatureGroupInspectorControls,
	TailwindFeatureGroupContext,
} from '../../../tailwind/inspector-controls'

import type {
	tBlockAttributes,
	tBlockEditProps,
} from '@ska/shared'

export interface SelectorEditProps {
	selector: string
	attributes: tBlockAttributes
	setAttributes: tBlockEditProps['setAttributes']
}

const SelectorEdit: React.FC<SelectorEditProps> = ({
	selector,
	attributes,
	setAttributes,
}) => {

	const [selectorName, setSelectorName] = useState(selector)

	const navigator = useNavigator()
	const [showNestedSelectors] = usePluginPreference('showNestedSelectors')

	const {
		name: blockName,
		groups,
	} = useContext(InspectorControlsContext)

	const dispatch = useSkaBlocksDispatch(attributes, setAttributes)
	const {setAttributes: dispatchSetAttributes} = dispatch

	const {
		skaBlocksSelectors = {},
	} = attributes

	const selectors = Object.keys(skaBlocksSelectors)

	const {
		[selector]: selectorAttributes = {},
	} = skaBlocksSelectors

	const setSelectorAttributes = useCallback((nextAttributes: tBlockAttributes) => {
		dispatchSetAttributes({
			skaBlocksSelectors: {
				...skaBlocksSelectors,
				[selector]: {
					...selectorAttributes,
					...nextAttributes,
				},
			},
		})
	}, [dispatchSetAttributes, skaBlocksSelectors, selector, selectorAttributes])

	const groupControls = groups.filter(group => group.hasValue(selectorAttributes, showNestedSelectors)).map(group => (
		<TailwindFeatureGroupContext.Provider
			key={group.groupId}
			value={group}
		>
			<FeatureGroupInspectorControls
				attributes={selectorAttributes}
				setAttributes={setSelectorAttributes}
			/>
		</TailwindFeatureGroupContext.Provider>
	))

	const fillProps = useMemo(() => ({
		selector,
		attributes: selectorAttributes,
		setAttributes: setSelectorAttributes,
	}), [selector, selectorAttributes, setSelectorAttributes])

	return <>
		<Panel>
			<PanelHeader
				label={__('Selector', 'ska-blocks')}
				menus={<>
					<NavigatorBackButton
						size='small'
						icon={chevronLeft}
						children={__('Back', 'ska-blocks')}
					/>
					<JsonView
						id={`ska-selector-${selector}`}
						label={sprintf(__('Selector: %s', 'ska-blocks'), selector)}
						value={() => ({
							selector,
							classNames: SkaBlocks.tailwind.getClassNames({skaBlocksSelectors: {[selector]: selectorAttributes}}),
							attributes: selectorAttributes,
						})}
					/>
				</>}
				actions={({onClose}) => [
					<MenuGroup key='actions'>
						<CopyItem
							attributes={selectorAttributes}
							onClose={onClose}
						/>
						<CopyValueItem
							attributes={selectorAttributes}
							onClose={onClose}
						/>
						<CopySelectorItem
							attributes={{[selector]: selectorAttributes}}
							onClose={onClose}
						/>
						<CopySelectorItem
							label={__('Cut selector', 'ska-blocks')}
							attributes={{[selector]: selectorAttributes}}
							onClose={() => {
								onClose()
								navigator.goBack()
								dispatch.removeSelector(selector)
							}}
						/>
						<MenuItem
							icon={trashIcon}
							children={__('Delete selector', 'ska-blocks')}
							onClick={() => {
								onClose()
								navigator.goBack()
								dispatch.removeSelector(selector)
							}}
						/>
					</MenuGroup>,
					<MenuGroup key='reset'>
						<ResetItem
							attributes={selectorAttributes}
							setAttributes={setSelectorAttributes}
							onClose={onClose}
						/>
					</MenuGroup>,
				]}
			/>
			<PanelBody>
				<VStack>
					<ActionInput
						placeholder={__('Selector…', 'ska-blocks')}
						clearLabel={_x('Clear value', 'action-input', 'ska-blocks')}
						value={selectorName}
						required
						actionable={selectorName !== selector}
						onChange={setSelectorName}
						onSubmit={nextValue => {

							const nextSelector = sanitizeVariant(nextValue)
							if(!nextSelector) {
								return
							}

							if(selectors.includes(nextSelector)) {
								return
							}

							dispatch.updateSelectorName({selector, nextSelector})

							const location = navigator?.location?.path || ''
							if(!location) {
								navigator.goTo('/')
							}

							const parts = location.split('/')
							parts[parts.length - 1] = sanitizeURIComponent(nextSelector)
							const nextLocation = parts.join('/')

							navigator.goTo(nextLocation, {replace: true, skipFocus: true})
						}}
					/>
					<Search
						name={blockName}
						attributes={selectorAttributes}
						setAttributes={setSelectorAttributes}
					/>
					<SelectorNav
						attributes={selectorAttributes}
						setAttributes={setSelectorAttributes}
					/>
				</VStack>
			</PanelBody>
			<Slot name='ska.blocks.InspectorControls.selector.before' fillProps={fillProps} />
			{groupControls.length > 0 && <Panel>{groupControls}</Panel>}
			<Slot name='ska.blocks.InspectorControls.selector.after' fillProps={fillProps} />
		</Panel>
	</>
}

export default SelectorEdit
