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

import {
	Panel as WPPanel,
	PanelHeader as WPPanelHeader,
	PanelBody as WPPanelBody,
	DropdownMenu,
	__experimentalHStack as HStack,
	MenuItem,
} from '@wordpress/components'

import {
	moreVertical as moreVerticalIcon,
	reset as resetIcon,
} from '@wordpress/icons'

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

import {
	useCopyToClipboard,
} from '@wordpress/compose'

import {
	store as noticesStore,
} from '@wordpress/notices'

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

import SkaBlocks from '../../../SkaBlocks'
import {useCopyTailwindClasses} from '../../hooks'
import {useSkaBlocksDispatch} from '../../reducer'

import {
	SEARCH_PLACEHOLDER,
	TAILWIND_VALUE_CLIPBOARD_PREFIX,
} from '../search'

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

import './style.scss'

export const Panel: React.FC<{children: React.ReactNode}> = ({children}) => {
	return <WPPanel className='ska-panel'>{children}</WPPanel>
}

export interface PanelHeaderProps {
	label: string | React.ReactNode
	menus?: React.ReactNode
	actions?: ({onClose}: {onClose: () => void}) => React.ReactNode | React.ReactNode[]
}

export const PanelHeader: React.FC<PanelHeaderProps> = ({
	label,
	menus = null,
	actions = null,
}) => {
	return (
		<WPPanelHeader>
			<HStack justify='start'>
				<SkaIcon />
				<h2>{label}</h2>
				{menus}
				{actions && (
					<DropdownMenu
						icon={moreVerticalIcon}
						label={__('More actions', 'ska-blocks')}
						toggleProps={{size: 'small'}}
					>
						{({onClose}) => actions({onClose})}
					</DropdownMenu>
				)}
			</HStack>
		</WPPanelHeader>
	)
}

export interface PanelBodyProps {
	className?: string
	children: React.ReactNode
}

export const PanelBody: React.FC<PanelBodyProps> = ({
	className = '',
	children,
}) => {
	return (
		<WPPanelBody
			className={cx('ska-panel__body', className)}
		>
			{children}
		</WPPanelBody>
	)
}

export type MenuItemProps = {
	clientId: string,
	attributes: tBlockEditProps['attributes'],
	setAttributes: tBlockEditProps['setAttributes'],
	onClose: () => void,
}

export const CopyItem: React.FC<Omit<MenuItemProps, 'clientId' | 'setAttributes'>> = ({
	attributes,
	onClose,
}) => {

	const classNames = SkaBlocks.tailwind.getClassNames(attributes)

	const {
		ref: copyRef,
		label: copyLabel,
		icon: CopyIcon,
	} = useCopyTailwindClasses(classNames, onClose)

	// @ts-ignore
	const icon = <CopyIcon /> as React.JSX.Element

	return (
		<MenuItem
			className='ska-menu-item--has-copy-icon'
			icon={icon}
			children={__('Copy Tailwind classes', 'ska-blocks')}
			label={copyLabel}
			aria-disabled={!classNames}
			disabled={!classNames}
			ref={copyRef}
		/>
	)
}

export const CopyValueItem: React.FC<Omit<MenuItemProps, 'clientId' | 'setAttributes'>> = ({
	attributes,
	onClose,
}) => {

	const {
		createSuccessNotice,
	} = useDispatch(noticesStore)

	const copyRef = useCopyToClipboard<HTMLButtonElement>(
		() => {

			const {
				skaBlocksSelectors,
				skaBlocksVariables,
			} = attributes

			const value = {
				...SkaBlocks.tailwind.getTailwindAttributes(attributes),
				...(skaBlocksVariables && Object.keys(skaBlocksVariables).length > 0 && {skaBlocksVariables}),
				...(skaBlocksSelectors && Object.keys(skaBlocksSelectors).length > 0 && {skaBlocksSelectors}),
			}

			return `${TAILWIND_VALUE_CLIPBOARD_PREFIX}${JSON.stringify(value)}`
		},
		() => {
			onClose()
			createSuccessNotice(
				sprintf(
					__('Copied value to clipboard. You can paste it to the "%s" input.', 'ska-blocks'),
					SEARCH_PLACEHOLDER
				),
				{type: 'snackbar'}
			)
		}
	)

	// @ts-ignore
	const icon = <SkaIcon /> as React.JSX.Element

	return (
		<MenuItem
			icon={icon}
			children={__('Copy value', 'ska-blocks')}
			label={__('Copy value', 'ska-blocks')}
			ref={copyRef}
		/>
	)
}

export const CopySelectorItem: React.FC<Omit<MenuItemProps, 'clientId' | 'setAttributes'> & {label?: string}> = ({
	label,
	attributes,
	onClose,
}) => {

	const {
		createSuccessNotice,
	} = useDispatch(noticesStore)

	const copyRef = useCopyToClipboard<HTMLButtonElement>(
		() => {

			const value = {
				skaBlocksSelectors: {
					...attributes,
				},
			}

			return `${TAILWIND_VALUE_CLIPBOARD_PREFIX}${JSON.stringify(value)}`
		},
		() => {
			createSuccessNotice(__('Copied selector to clipboard.', 'ska-blocks'), {type: 'snackbar'})
			onClose()
		}
	)

	// @ts-ignore
	const icon = <SkaIcon /> as React.JSX.Element

	return (
		<MenuItem
			icon={icon}
			children={label || __('Copy selector', 'ska-blocks')}
			label={label || __('Copy selector', 'ska-blocks')}
			ref={copyRef}
		/>
	)
}

export const ResetItem: React.FC<Omit<MenuItemProps, 'clientId'>> = ({
	attributes,
	setAttributes,
	onClose,
}) => {

	const {
		skaBlocksSelectors = {},
	} = attributes

	const tailwindClasses = SkaBlocks.tailwind.getClassNames(attributes)
	const hasClasses = !!tailwindClasses
	const hasSelectors = Object.keys(skaBlocksSelectors).length > 0
	const dispatch = useSkaBlocksDispatch(attributes, setAttributes)

	return <>
		{hasClasses && (
			<MenuItem
				icon={resetIcon}
				children={__('Reset classes', 'ska-blocks')}
				aria-disabled={!hasClasses}
				disabled={!hasClasses}
				onClick={() => {
					dispatch.setAttributes({
						...Object.fromEntries(
							SkaBlocks.tailwind.features.map(feature => [feature.id, undefined])
						),
					})
					onClose()
				}}
			/>
		)}
		{hasSelectors && (
			<MenuItem
				icon={resetIcon}
				children={__('Reset selectors', 'ska-blocks')}
				aria-disabled={!hasSelectors}
				disabled={!hasSelectors}
				onClick={() => {
					dispatch.setAttributes({skaBlocksSelectors: undefined})
					onClose()
				}}
			/>
		)}
		<MenuItem
			icon={resetIcon}
			children={__('Reset all', 'ska-blocks')}
			aria-disabled={!hasClasses && !hasSelectors}
			disabled={!hasClasses && !hasSelectors}
			onClick={() => {
				dispatch.setAttributes({
					...Object.fromEntries(
						SkaBlocks.tailwind.features.map(feature => [feature.id, undefined])
					),
					skaBlocksSelectors: undefined,
					skaBlocksVariables: undefined,
				})
				onClose()
			}}
		/>
	</>
}
