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

import {
	createContext,
	useState,
} from '@wordpress/element'

import {
	Panel as WPPanel,
	PanelBody,
	MenuGroup,
	MenuItem,
	__experimentalVStack as VStack,
	__experimentalNavigatorProvider as NavigatorProvider,
	__experimentalNavigatorScreen as NavigatorScreen,
	withFilters,
	Slot,
} from '@wordpress/components'

import {
	useDispatch,
} from '@wordpress/data'

import {
	css_beautify,
	// @ts-expect-error
} from 'js-beautify'

import {
	settings as settingsIcon,
	help as helpIcon,
} from '@wordpress/icons'

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

import {
	Panel,
	PanelHeader,
	CopyItem,
	ResetItem,
	CopyValueItem,
} from './panel'

import Search from './search'
import FeatureGroupInspectorControls from './FeatureGroupInspectorControls'

import HelpModal from './help-modal'
import {usePluginPreference} from '../../store'

import {
	PLUGIN_ID,
} from '../../plugins/options'

import {
	useHasPermissions,
} from '../../plugins/permissions'

import {
	useSkaBlocks,
	useTailwindConfigVersion,
} from '../hooks'

import type {
	TailwindAttributes,
	TailwindFeature,
	TailwindFeatureGroup,
	TailwindFeatures,
	TailwindFeaturesList,
} from '../../types'

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

export interface InspectorControlsProps {
	blockProps: tBlockEditProps<TailwindAttributes>
	label: TailwindFeatures['label']
	groups: TailwindFeatures['groups']
	children?: React.ReactNode
}

const SettingsItem: React.FC<{onClose: () => void}> = () => {

	const {
		enableComplementaryArea,
	} = useDispatch('core/interface'/*interfaceStore*/) // Using the store object logs `Store "core/interface" is already registered.` in console.

	return (
		<MenuItem
			icon={settingsIcon}
			children={__('Plugin settings', 'ska-blocks')}
			onClick={() => enableComplementaryArea('core/edit-post', `${PLUGIN_ID}/${PLUGIN_ID}`)}
		/>
	)
}

interface InspectorControlsContextType extends tBlockEditProps<TailwindAttributes> {
	groups: TailwindFeatures['groups']
	features: TailwindFeaturesList
}

export const InspectorControlsContext = createContext<InspectorControlsContextType>({} as InspectorControlsContextType)

const NO_BLOCK_PROPS: tBlockEditProps = {
	clientId: '',
	name: '',
	isSelected: false,
	isSelectionEnabled: false,
	attributes: {},
	setAttributes: _nextAttributes => {},
	insertBlocksAfter: () => {},
	context: null,
}

export const useInspectorControlsContextValue = (blockProps: tBlockEditProps = NO_BLOCK_PROPS): InspectorControlsContextType => {

	const {
		attributes,
	} = blockProps

	const skaBlocks = useSkaBlocks()
	const features = skaBlocks.tailwind.getFeaturesList(attributes)

	return {
		...blockProps,
		features,
		groups: skaBlocks.tailwind.groups,
	}
}

export const TailwindFeatureGroupContext = createContext<TailwindFeatureGroup>({} as TailwindFeatureGroup)
export const TailwindFeatureContext = createContext<TailwindFeature>({} as TailwindFeature)

interface TailwindFeatureClassNamesType {
	classNames: string
	selectorsClassNames: string
}
export const TailwindFeatureClassNamesContext = createContext<TailwindFeatureClassNamesType>({
	classNames: '',
	selectorsClassNames: '',
})

/**
 * This component renders InspectorControls for a block that supports Tailwind.
 */
const InspectorControls: React.FC<InspectorControlsProps> = ({
	blockProps,
	label,
	groups,
	children = null,
}) => {

	const {
		name,
		attributes,
		setAttributes,
	} = blockProps

	const [helpModalOpen, setHelpModalOpen] = useState(false)
	const [showNestedSelectors] = usePluginPreference('showNestedSelectors')

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

	return (
		<InspectorControlsContext.Provider value={useInspectorControlsContextValue(blockProps)}>
			<WPPanel className='ska-blocks__tailwind-inspector-controls'>
				<NavigatorProvider initialPath='/' style={{overflowX: 'initial'}}>
					<NavigatorScreen path='/' style={{maxHeight: 'initial', overflowX: 'initial'}}>
						<Panel>
							<PanelHeader
								label={label}
								menus={<>
									<JsonView
										label={__('Block attributes', 'ska-blocks')}
										size='small'
										value={() => {
											const {skaBlocks, ...restAttributes} = attributes
											if(!skaBlocks) {
												return {
													...restAttributes,
												}
											}
											const {css = ''} = skaBlocks
											return {
												skaBlocks: {
													...skaBlocks,
													...(css.trim().length > 0 ? {
														css: `\n${css_beautify(css)}\n`,
													} : {}),
												},
												...restAttributes,
											}
										}}
									/>
									<Slot name='ska.blocks.InspectorControls.menus' />
								</>}
								actions={({onClose}) => [
									<MenuGroup key='actions'>
										<CopyItem
											attributes={attributes}
											onClose={onClose}
										/>
										<CopyValueItem
											attributes={attributes}
											onClose={onClose}
										/>
										<SettingsItem
											{...blockProps}
											onClose={onClose}
										/>
										<MenuItem
											icon={helpIcon}
											children={__('Help', 'ska-blocks')}
											onClick={() => {
												onClose()
												setHelpModalOpen(true)
											}}
										/>
									</MenuGroup>,
									<Slot
										key='ska.blocks.InspectorControls.actions'
										name='ska.blocks.InspectorControls.actions'
										fillProps={{...blockProps, onClose}}
									/>,
									<MenuGroup key='reset'>
										<Slot name='ska.blocks.InspectorControls.actions.reset' fillProps={{...blockProps, onClose}} />
										<ResetItem
											attributes={attributes}
											setAttributes={setAttributes}
											onClose={onClose}
										/>
									</MenuGroup>,
								]}
							/>
							<PanelBody>
								<VStack>
									<Search
										name={name}
										attributes={attributes}
										setAttributes={setAttributes}
									/>
									<Slot name='ska.blocks.InspectorControls.head' />
								</VStack>
							</PanelBody>
						</Panel>
						<Slot name='ska.blocks.InspectorControls.before' />
						{groupControls.length > 0 && <Panel>{groupControls}</Panel>}
						<Slot name='ska.blocks.InspectorControls.after' />
					</NavigatorScreen>
					<Slot name='ska.blocks.InspectorControls.screens' />
				</NavigatorProvider>
			</WPPanel>
			{helpModalOpen && <HelpModal onRequestClose={() => setHelpModalOpen(false)} />}
			<>{children}</>
		</InspectorControlsContext.Provider>
	)
}

/**
 * Only render InspectorControls if the current user has "unfiltered_html" capabilities.
 */
const BaseInspectorControls: React.FC<InspectorControlsProps> = props => {

	const hasPermissions = useHasPermissions()
	const ver = useTailwindConfigVersion()

	if(!hasPermissions) {
		return null
	}

	if(ver < 0) {
		return null // Probably LightningCSS still initializing
	}

	return <InspectorControls {...props} />
}

export default withFilters('ska.blocks.InspectorControls')(BaseInspectorControls) as any as typeof BaseInspectorControls
