import React from 'react'
import PropTypes from 'prop-types'
import { View } from 'react-native'
import { Icon } from '../Icon/Icon'
import { useVariants } from '../utils/useVariants'

export const tokenTypes = {
  itemIconSize: PropTypes.number.isRequired,
  itemIconColor: PropTypes.string.isRequired,
  listGutter: PropTypes.number.isRequired,
  iconMarginTop: PropTypes.number.isRequired,
  bulletIcon: PropTypes.elementType.isRequired
}

const selectContainerStyles = ({ listGutter }) => ({
  marginInlineEnd: listGutter,
  display: 'flex',
  alignItems: 'flex-start'
})
const selectBulletStyles = ({ itemIconSize }) => ({
  width: itemIconSize,
  height: itemIconSize,
  alignItems: 'center',
  justifyContent: 'center',
  flexShrink: 0
})

const getIconColorVariants = (iconVariants) =>
  iconVariants?.filter((variant) => variant[0] === 'color').map((variant) => variant[1])

/**
 * Subcomponent used within ListItem and similar components for rendering bullets or icons
 * that sit alongside a ListIconContent in a { flexDirection: row } container.
 *
 * It's the responsibility of themes to make sure that the supplied tokens align the
 * icon or bullet nicely against the first line of text in a ListIconContent.
 */
export const ListItemMark = React.forwardRef(({ icon, iconColor, iconSize, tokens = {} }, ref) => {
  const themeTokens = typeof tokens === 'function' ? tokens() : tokens
  const containerStyles = selectContainerStyles(themeTokens)

  const iconVariants = useVariants('Icon')
  const iconColorVariants = getIconColorVariants(iconVariants)

  if (icon) {
    const { itemIconSize, itemIconColor } = themeTokens
    const finalIconSize = iconSize ?? itemIconSize
    const finalIconColor =
      iconColor && !iconColorVariants?.includes(iconColor) ? iconColor : itemIconColor

    return (
      <View style={containerStyles}>
        <Icon
          icon={icon}
          tokens={{
            size: finalIconSize,
            color: finalIconColor
          }}
          variant={{
            ...(iconColorVariants?.includes(iconColor) && { color: iconColor })
          }}
        />
      </View>
    )
  }

  const { itemIconSize, itemIconColor } = themeTokens
  const bulletStyles = selectBulletStyles(themeTokens)

  return (
    <View style={containerStyles} ref={ref}>
      <View style={bulletStyles}>
        <Icon
          icon={themeTokens.bulletIcon}
          tokens={{
            color: itemIconColor,
            size: itemIconSize
          }}
        />
      </View>
    </View>
  )
})

ListItemMark.displayName = 'ListItemMark'

ListItemMark.propTypes = {
  tokens: PropTypes.shape(tokenTypes).isRequired,
  /**
   * Renders side item icon
   */
  icon: PropTypes.elementType,
  /**
   * Will set display icon color
   */
  iconColor: PropTypes.string,
  /**
   * Allow the user define the icon size
   */
  iconSize: PropTypes.number
}
