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

import {
	hasBlockSupport,
	getBlockSupport,
	// @ts-expect-error
} from '@wordpress/blocks'

import {
	addFilter,
} from '@wordpress/hooks'

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

import {
	InspectorControlsProps,
} from '../../tailwind/inspector-controls'

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

import type {
	tBlockNameOrType,
	tBlockType,
} from '@ska/shared'

import {
	VariablesInspectorControls,
} from './components'

import {
	withVariablesClassNames,
} from './util'

import {
	parseJson,
} from '@ska/utils'

export * from './components'
export * from './util'
export * from './types'

export const VARIABLES_SUPPORT_KEY = 'skaBlocksVariables'
export const VARIABLES_SUPPORT_DEFAULT_ENABLED = false
export const hasVariablesSupport = (block: tBlockNameOrType) => {
	// return hasBlockSupport(block, VARIABLES_SUPPORT_KEY, VARIABLES_SUPPORT_DEFAULT_ENABLED) || hasBlockSupport(block, 'customClassName', true)
	return hasBlockSupport(block, 'customClassName', true)
}

export const VARIABLES_VALUE_CLIPBOARD_PREFIX = 'ska-blocks-variables:'
export const handlePasteVariables = ({content, apply, onSuccess, onError}: {
	content: string,
	apply: (record: VariablesValue['record']) => void,
	onSuccess: () => void,
	onError: () => void,
}) => {

	if(content.indexOf(VARIABLES_VALUE_CLIPBOARD_PREFIX) !== 0) {
		return false
	}

	const record = parseJson(content.replace(VARIABLES_VALUE_CLIPBOARD_PREFIX, ''), 'Pasted variables', false)
	if(record === false) {
		onError()
		return false
	}

	apply(record)
	onSuccess()
	return true
}

/**
 * Default value can be provided in block `supports` attribute.
 *
 * @example
 * ```json
 * 	"supports": {
 * 		"skaBlocksVariables": {
 * 			"aria-label": "Text"
 * 		}
 * 	}
 * ```
 */
const getDefaultValue = (block: tBlockType) => {

	const support = getBlockSupport(block, VARIABLES_SUPPORT_KEY, VARIABLES_SUPPORT_DEFAULT_ENABLED)

	return {
		...(typeof support === 'object' && {
			record: {
				...support,
			},
		}),
	}
}

const withCustomAttributes = (settings: tBlockType) => {

	if(!hasVariablesSupport(settings)) {
		return settings
	}

	if(!settings.attributes.skaBlocksVariables) {

		const defaultValue = getDefaultValue(settings)

		Object.assign(settings.attributes, {
			skaBlocksVariables: {
				type: 'object',
				...(Object.keys(defaultValue).length > 0 && {
					default: defaultValue,
				}),
			},
		})
	}

	return settings
}

const withVariablesControls = createHigherOrderComponent(
	(BaseInspectorControls: React.FC<InspectorControlsProps>) => (props: InspectorControlsProps) => {

		const {
			children,
			...restProps
		} = props

		return (
			<BaseInspectorControls {...restProps}>
				{children}
				<VariablesInspectorControls />
			</BaseInspectorControls>
		)
	},
	'withSkaBlocksVariablesControls'
)

export default () => {
	addFilter('blocks.registerBlockType', 'ska-blocks/with-variables-attribute', withCustomAttributes)
	addFilter('ska.blocks.InspectorControls', 'ska-blocks/with-variables-controls', withVariablesControls)
	addFilter('ska.blocks.tailwindClassNames', 'ska-blocks/with-variables-class-names', withVariablesClassNames)
}
