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

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

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

import {
	RadioProps,
} from '.'

import {
	type ArbitraryValueType,
} from '../..'

export interface EditableButtonProps {
	type: ArbitraryValueType
	label: string
	value?: string
	colorValue?: string
	isActive?: boolean
	isSmall?: RadioProps['isSmall']
	onAdd?: RadioProps['onAdd']
	onChange?: (nextValue: string) => void
	ButtonComponent?: React.FC<any>
}

const getPrepend = (type: ArbitraryValueType) => {
	switch(type) {
		case 'arbitrary':
			return '['
		case 'variable':
			return '('
		case 'name':
			return '/'
	}
	return <RawHTML children={`&nbsp;`} />
}

const getAppend = (type: ArbitraryValueType) => {
	switch(type) {
		case 'arbitrary':
			return ']'
		case 'variable':
			return ')'
		case 'name':
			return <RawHTML children={`&nbsp;`} />
	}
	return <RawHTML children={`&nbsp;`} />
}

const EditableButton: React.FC<EditableButtonProps> = ({
	type = 'bare',
	label,
	value = '',
	colorValue,
	isActive = false,
	isSmall = false,
	onAdd,
	onChange,
	ButtonComponent = Button,
}) => {

	const [modified, setModified] = useState(false)
	const inputRef = useRef<HTMLSpanElement | null>(null)

	return (
		<ButtonComponent
			className='ska-tailwind-radio__input'
			variant={isActive ? 'primary' : 'secondary'}
			size={isSmall ? 'small' : undefined}
			label={label}
			showTooltip
			tabIndex={-1}
			{...(colorValue && {colorValue})}
			children={<>
				{getPrepend(type)}
				{(
					<span /* eslint jsx-a11y/no-static-element-interactions: "off" */
						contentEditable
						suppressContentEditableWarning
						key={value}
						data-type={type}
						{...(modified && {'data-modified': true})}
						{...((!value && type === 'bare') && {'data-indicator': true})}
						role='textbox'
						aria-multiline={false}
						aria-label={label}
						tabIndex={0}
						ref={inputRef}
						onPaste={e => {
							e.preventDefault()
							e.stopPropagation()
							if(inputRef.current) {
								const currentText = inputRef.current.innerText
								const pastedText = e.clipboardData.getData('text/plain').trim().replace(/(\r\n|\n|\r|\t)/gm, ' ').trim()
								const {anchorOffset = 0, focusOffset = 0} = inputRef.current?.ownerDocument?.defaultView?.getSelection() || {}
								const nextText = `${currentText.substring(0, anchorOffset)}${pastedText}${currentText.substring(focusOffset, currentText.length)}`
								inputRef.current.innerText = nextText
								const selection = inputRef.current?.ownerDocument?.defaultView?.getSelection()
								// TODO: this can be perfected by capturing the original selection anchorOffset and adding pastedText.length
								if(selection) {
									const range = selection.getRangeAt(0)
									const index = nextText.indexOf(pastedText)
									const nextIndex = index > 0 ? Math.min(index + pastedText.length, nextText.length) : pastedText.length
									if(inputRef.current.firstChild) {
										range.setStart(inputRef.current.firstChild, nextIndex)
										range.setEnd(inputRef.current.firstChild, nextIndex)
									}
								}
							}
							return false
						}}
						onKeyDown={e => {
							if(e.key === 'Enter') {

								e.preventDefault()
								e.stopPropagation()

								if(!inputRef.current) {
									return
								}

								const nextValue = inputRef.current.innerText.trim().replaceAll(' ', '_')

								if(onChange) {

									if(!nextValue) {
										return
									}

									setModified(false)

									if(nextValue === value) {
										return
									}

									onChange(nextValue)
									return
								}

								if(onAdd) {

									if(nextValue) {
										onAdd(nextValue)
										inputRef.current.innerText = ''
									}
								}
							}
						}}
						onKeyUp={e => {
							if(e.key === 'Enter') {
								return
							}
							if(!modified && inputRef.current && inputRef.current.innerText !== value) {
								setModified(true)
							}
						}}
						children={value}
					/>
				)}
				{getAppend(type)}
			</>}
			onFocus={(e: React.FocusEvent) => {

				if(e.relatedTarget === inputRef.current) {
					return
				}

				if(isActive) {

					const defaultVariantLabel = _x('Default', 'Label for "default state" variant', 'ska-blocks')
					const isDefaultVariantEditableButton = label === defaultVariantLabel && value === defaultVariantLabel

					if(isDefaultVariantEditableButton) {

						/** Special case: when popover opens and focuses "Default" variant don't focus the `[contentEditable]`. */
						if(e.relatedTarget && e.relatedTarget.getAttribute('aria-haspopup') === 'true') {
							inputRef?.current?.blur()
							return
						}

						/** Special case: select all text when focusing "Default" variant editable button. */
						if(inputRef.current) {
							const range = document.createRange()
							range.selectNodeContents(inputRef.current)
							const selection = window.getSelection()
							if(selection) {
								selection.removeAllRanges()
								selection.addRange(range)
							}
							return
						}
					}
				}

				inputRef?.current?.focus()
			}}
		/>
	)
}

export default EditableButton
