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

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

import {
	Notice,
} from '@wordpress/components'

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

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

import type {
	TailwindParserResults,
} from '../../../types'

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

import './style.scss'

export interface useParseArgs {
	name?: tBlockName
	attributes: tBlockAttributes
	setAttributes: (attributes: Partial<tBlockAttributes>) => void
}

export const useParse = ({
	name,
	attributes,
	setAttributes,
}: useParseArgs): [(classNames: string) => void, React.ReactNode] => {

	const {parser} = useSkaBlocks()
	const dispatch = useSkaBlocksDispatch(attributes, setAttributes)
	const [input, setInput] = useState('')
	const [errors, setErrors] = useState<TailwindParserResults[]>([])

	/**
	 * No point running `hasBlockSupport(block, 'customClassName', true)` as this feature
	 * is usually only for blocks that support Tailwind or non-blocks with no name (theme presets).
	 */
	const supportsCustomClassName = true // !!name Now using "custom" custom class names

	const parse = (input: string) => {
		const [nextAttributes, errors] = parser.applyClasses(input, attributes)
		dispatch.setAttributes(nextAttributes)
		setErrors(errors)
		setInput(errors.map(({input}) => input).join(' '))
	}

	const Errors = errors.length > 0 ? (
		<div className='ska-parse'>
			{errors.map(err => {

				const clearClass = (className: string) => {
					setInput(input.split(' ').filter(v => v !== className).join(' '))
				}

				const dismiss = () => {
					setErrors(errors.filter(e => e.input !== err.input))
				}

				// @ts-ignore
				const actions = err.suggestions.map(suggestion => {

					const {
						id,
						label = '',
						optionLabel = '',
					} = suggestion

					const displayLabel = optionLabel ? (
						!label || optionLabel.indexOf(label) === 0
							? optionLabel // When the label is `Scale` and optionLabel is `Scale X` display just the latter
							: `${label} (${optionLabel})` // but when it's something like `Divide width` and `Horizontal` then combine them
					) : label || id // If there's no labels at all fall back to ID so at least something is shown

					return {
						label: displayLabel,
						isSmall: true,
						className: 'is-small',
						onClick: () => {
							dispatch.setAttributes(parser.applyFeature(
								attributes,
								parser.getFeatureClass(err.tailwindClass, suggestion)
							))
							clearClass(err.input)
							dismiss()
						},
					}
				// @ts-ignore
				}).concat([
					...(supportsCustomClassName ? [
						{
							label: __('Add to classes', 'ska-blocks'),
							isSmall: true,
							className: 'is-small',
							variant: 'primary',
							noDefaultClasses: true,
							onClick: () => {
								dispatch.addClass(err.input)
								clearClass(err.input)
								dismiss()
							},
						},
					] : []),
					{
						label: __('Add selector', 'ska-blocks'),
						isSmall: true,
						className: 'is-small',
						variant: 'secondary',
						noDefaultClasses: true,
						onClick: () => {
							dispatch.addSelector(err.input)
							clearClass(err.input)
							dismiss()
						},
					},
				])

				return (
					<Notice
						key={err.input}
						className='ska-parse__error'
						status='warning'
						isDismissible
						onRemove={dismiss}
						actions={actions}
					>
						<h4>{err.suggestions.length > 0 ? __('Not sure what that is', 'ska-blocks') : __(`Doesn't look like anything to me`, 'ska-blocks')}</h4>
						<p><code>{err.input}</code></p>
					</Notice>
				)
			})}
		</div>
	) : null

	return [parse, Errors]
}
