import * as React from 'react'
import cx from 'classnames'

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

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

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

import type {
	ButtonProps as WPButtonProps,
} from '@wordpress/components/build-types/button/types'

import './style.scss'

export type ButtonProps = Omit<WPButtonProps, 'tooltipPosition'> & {
	isSmall?: boolean
	tooltipPosition?: 'top left' | 'top right' | 'bottom left' | 'bottom right'
}

const truthyAriaPressedValues = [true, 'true', 'mixed']

/**
 * WP button clone that does tooltips differently (for performance) and probably lacks some accessibility features of the original.
 */
function Button(props: ButtonProps, ref: React.ForwardedRef<any>) {

	const {
		__next40pxDefaultSize,
		isBusy,
		isDestructive,
		className,
		disabled,
		icon,
		iconPosition = 'left',
		iconSize,
		showTooltip,
		tooltipPosition,
		shortcut,
		label,
		children,
		size = 'default',
		isSmall = false, // @deprecated
		text,
		variant,
		description,
		isPressed: __deprecatedIsPressed,
		...buttonOrAnchorProps
	} = props

	const {
		href,
		target,
		'aria-checked': ariaChecked,
		'aria-pressed': ariaPressed,
		'aria-selected': ariaSelected,
		...additionalProps
	} = 'href' in buttonOrAnchorProps ? buttonOrAnchorProps : {href: undefined, target: undefined, ...buttonOrAnchorProps}

	const instanceId = useInstanceId(Button, 'components-button__description')

	const hasChildren = (
		(typeof children === 'string' && !!children)
		|| (
			Array.isArray(children)
			&& children?.[0]
			&& children[0] !== null
			&& children?.[0]?.props?.className !== 'components-tooltip' // Tooltip should not considered as a child
		)
	)

	const classes = cx('ska-button components-button', className, {
		'is-next-40px-default-size': __next40pxDefaultSize,
		'is-secondary': variant === 'secondary',
		'is-primary': variant === 'primary',
		'is-small': size === 'small' || isSmall,
		'is-compact': size === 'compact',
		'is-tertiary': variant === 'tertiary',

		'is-pressed': truthyAriaPressedValues.includes(ariaPressed as any),
		'is-pressed-mixed': ariaPressed === 'mixed',

		'is-busy': isBusy,
		'is-link': variant === 'link',
		'is-destructive': isDestructive,
		'has-text': !!icon && (hasChildren || text),
		'has-icon': !!icon,
	})

	const shouldShowTooltip = showTooltip && !!label
	const tooltip = label

	const isDisabled = !!disabled
	const Tag = href !== undefined && !isDisabled ? 'a' : 'button'

	const descriptionId = description ? instanceId : undefined
	const describedById = additionalProps['aria-describedby'] || descriptionId
	const commonProps = {
		className: classes,
		'aria-label': additionalProps['aria-label'] || label,
		'aria-describedby': describedById,
		ref,
		...(shouldShowTooltip && {
			'data-ska-tooltip': tooltip,
			...(tooltipPosition && {
				'data-ska-tooltip-position': tooltipPosition,
			}),
		}),
	}

	const elementChildren = (
		<>
			{icon && iconPosition === 'left' && <Icon icon={icon} size={iconSize} />}
			{text && <>{text}</>}
			{children}
			{icon && iconPosition === 'right' && <Icon icon={icon} size={iconSize} />}
		</>
	)

	if(Tag === 'a') {
		return (
			<a
				href={href}
				target={target}
				{...(additionalProps as React.HTMLAttributes<HTMLAnchorElement>)}
				{...commonProps}
			>
				{elementChildren}
			</a>
		)
	}

	return (
		<button
			type='button'
			disabled={isDisabled}
			// aria-checked={ariaChecked}
			aria-pressed={ariaPressed}
			// aria-selected={ariaSelected}
			{...(additionalProps as React.HTMLAttributes<HTMLButtonElement>)}
			{...commonProps}
		>
			{elementChildren}
		</button>
	)
}

export default forwardRef(Button)
