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

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

import {
	__experimentalNavigatorButton as NavigatorButton,
} from '@wordpress/components'

import {
	edit as editIcon,
	styles as stylesIcon,
	filter as filterIcon,
	link as linkIcon,
	linkOff as linkOffIcon,
} from '@wordpress/icons'

import {
	ArrayEditor,
} from '../../../components'

import {
	isManagedPreset,
	usePresetOptionsEdit,
	PresetsModal,
	type PresetSlug,
	type ResolvedBlockPreset,
} from '..'

import type {
	ArrayValueControlProps,
	ButtonGridButtonProps,
} from '@ska/components'

import type {
	SkaBlocksActionTypes,
} from '../../../tailwind/reducer'

export interface PresetsListProps {
	presets: ResolvedBlockPreset[]
	dispatch: SkaBlocksActionTypes
}

const PresetRow: React.FC<ArrayValueControlProps> = ({value}) => {

	const [presetsSelect] = usePresetOptionsEdit()

	const {
		ref,
		title,
		loading,
	} = presetsSelect.getPreset(value)

	return (
		<div
			className={cx('ska-preset-row', {
				'ska-preset-row--managed': isManagedPreset(value),
				[`ska-preset-row--loading-${loading}`]: !!loading,
				'ska-preset-row--not-found': ref === '404',
			})}
		>
			<span>
				{title}
				{loading === 'off' && ` (${__('Loading disabled', 'ska-blocks')})`}
			</span>
		</div>
	)
}

const PresetsList: React.FC<PresetsListProps> = ({
	presets: blockPresets,
	dispatch,
}) => {

	const [presetsSelect] = usePresetOptionsEdit()
	const [replace, setReplace] = useState<PresetSlug | undefined>(undefined)

	/**
	 * Hack for dispatch.presetToggleStatic().
	 * For performance reasons the dispatch only loads dynamic presets that the block currently has (which is almost always 0),
	 * so when a preset type is toggled it's not yet loaded/unloaded and won't be available when applying Tailwind.
	 * This triggers a second update that will process the attributes again, accounting for the change in presets.
	 */
	const shouldForceUpdateRef = useRef(false)
	useEffect(() => {
		if(!shouldForceUpdateRef.current) {
			return
		}
		dispatch.setAttributes({})
		shouldForceUpdateRef.current = false
	}, [dispatch])

	return <>
		<ArrayEditor
			id='ska-presets'
			showIndex={false}
			value={blockPresets.map(({id}) => id.toString())}
			onChange={ids => dispatch.updateBlockPresets(
				ids.map(slug => blockPresets.find(({id}) => id === slug)) as any as ResolvedBlockPreset[]
			)}
			ValueControl={PresetRow}
			getButtons={(buttons, presetSlug) => {

				const preset = presetsSelect.getPreset(presetSlug)

				if(preset.ref === '404') {
					return [
						{
							label: __('Replace preset', 'ska-blocks'),
							icon: linkIcon,
							onClick: () => {
								setReplace(presetSlug)
							},
						},
						buttons[buttons.findIndex(({key}) => key === 'remove-row')],
					] as ButtonGridButtonProps[]
				}

				const {
					attrs,
				} = preset

				const {
					isStatic = false,
				} = blockPresets.find(({id}) => presetSlug === id) || {}

				return [
					buttons[buttons.findIndex(({key}) => key === 'move-up')],
					{
						label: __('Merge preset', 'ska-blocks'),
						icon: linkOffIcon,
						onClick: () => dispatch.mergePreset({id: presetSlug, presetAttributes: JSON.parse(attrs)}),
					},
					{
						label: __('Edit preset', 'ska-blocks'),
						icon: editIcon,
						iconProps: {size: 14},
						as: NavigatorButton,
						path: `/preset/${presetSlug}`,
					},
					buttons[buttons.findIndex(({key}) => key === 'move-down')],
					{
						label: isStatic ? __('Switch to dynamic', 'ska-blocks') : __('Switch to static', 'ska-blocks'),
						icon: isStatic ? stylesIcon : filterIcon,
						className: cx({
							'ska-presets__toggle-static': isStatic,
							'ska-presets__toggle-dynamic': !isStatic,
						}),
						iconProps: {size: 14},
						onClick: () => {
							dispatch.presetToggleStatic(presetSlug)
							shouldForceUpdateRef.current = true
						},
					},
					{
						...buttons[buttons.findIndex(({key}) => key === 'remove-row')],
						label: __('Remove preset', 'ska-blocks'),
					},
				] as ButtonGridButtonProps[]
			}}
		/>
		{replace && (
			<PresetsModal
				onAddPreset={slug => {
					dispatch.batch([
						dispatch.actions.removePreset(replace),
						dispatch.actions.addPreset(slug),
					])
					setReplace(undefined)
				}}
				onRemovePreset={slug => dispatch.removePreset(slug)}
				onRequestClose={() => setReplace(undefined)}
			/>
		)}
	</>
}

export default PresetsList
