import React, { forwardRef } from 'react'
import PropTypes from 'prop-types'
import { css } from '@mxenabled/cssinjs'
import { useTokens } from '@kyper/tokenprovider'

export const ICON_BUTTON_VARIANTS = {
  TRANSPARENT: 'transparent',
  TRANSPARENT_TERTIARY: 'transparent-tertiary',
}

export const IconButton = forwardRef(
  (
    {
      children,
      className = '',
      disabled,
      largeTouchTarget = true,
      onClick,
      variant = ICON_BUTTON_VARIANTS.TRANSPARENT,
      ...rest
    },
    ref,
  ) => {
    const tokens = useTokens()
    const styles = getStyles(tokens, { disabled, largeTouchTarget, variant })

    return (
      <button
        aria-disabled={disabled}
        className={`${css(styles)} kyper-icon-button ${className}`}
        onClick={!disabled ? onClick : e => e.preventDefault()}
        ref={ref}
        type="button"
        {...rest}
      >
        {children}
      </button>
    )
  },
)

const getStyles = (tokens, { disabled, largeTouchTarget, variant }) => ({
  display: 'inline-flex',
  alignItems: 'center',
  justifyContent: 'center',
  border: 'none',
  cursor: disabled ? 'not-allowed' : 'pointer',
  whiteSpace: 'nowrap',
  fontSize: tokens.FontSize.Button,
  fontFamily: tokens.Font.Semibold,
  position: 'relative',
  backgroundColor: 'transparent',
  color:
    variant === ICON_BUTTON_VARIANTS.TRANSPARENT
      ? tokens.TextColor.ButtonTransparent
      : tokens.TextColor.ButtonTransparentTertiary,
  margin: 0,
  padding: 0,
  transition: `all ${tokens.Time.Short}ms ${tokens.Easing.Default}`,
  height: largeTouchTarget ? 44 : 'auto',
  width: largeTouchTarget ? 44 : 'auto',
  '& > svg': {
    padding: tokens.Spacing.Tiny,
    borderRadius: tokens.BorderRadius.Button,
    boxSizing: 'initial',
  },
  '&:focus': {
    outline: 'none',
    '& > svg': {
      boxShadow: tokens.BoxShadow.FocusRingDefault,
    },
  },
  '&:hover': {
    '& > svg': {
      color: disabled
        ? tokens.TextColor.ButtonTransparentDisabled
        : tokens.TextColor.ButtonTransparentHover,
      backgroundColor: disabled ? 'transparent' : tokens.BackgroundColor.ButtonTransparentHover,
    },
  },
  ...(disabled
    ? {
        color: tokens.TextColor.ButtonTransparentDisabled,
      }
    : null),
})

IconButton.propTypes = {
  /**
   * ** This throws a console error if you forget to pass in an aria-label for the screenreader
   */
  ariaLabelCheck: (props, _, componentName) => {
    /* eslint-disable object-shorthand */
    if (!props['label'] && !props['aria-label']) {
      return new Error(
        `For screenreaders you must use the aria-label prop when using the ${componentName} component.`,
      )
    }
    return null
  },
  className: PropTypes.string,
  /**
   * ** Disables the onClick function and adds `aria-disabled` so that the button is still tabbable for accessibility.
   */
  disabled: PropTypes.bool,
  /**
   * ** This makes the button clickable area 44px square to make it more accessible.
   */
  largeTouchTarget: PropTypes.bool,
  onClick: PropTypes.func,
  /**
   * ** You can import `ICON_BUTTON_VARIANTS` if you want to use the constants instead of typing the string values.
   */
  variant: PropTypes.oneOf(Object.values(ICON_BUTTON_VARIANTS)),
}

IconButton.displayName = 'IconButton'
