import React from 'react'
import PropTypes from 'prop-types'

import { View, StyleSheet } from 'react-native'
import { wrapStringsInText } from '../utils/children'
import { useTheme } from '../ThemeProvider/useTheme'
import { applyTextStyles } from '../ThemeProvider/utils/styles'
import { scaleLineHeightRatio } from '../utils/a11y/fontScaleConverter'
import { useFontScaleConverter } from '../utils/a11y/useFontScaleConverter'

export const tokenTypes = {
  itemFontWeight: PropTypes.string.isRequired,
  itemFontSize: PropTypes.number.isRequired,
  itemLineHeight: PropTypes.number.isRequired,
  itemFontName: PropTypes.string.isRequired,
  itemFontColor: PropTypes.string
}

const selectItemTextStyles = (
  { itemFontWeight, itemFontSize, itemLineHeight, itemFontName, itemFontColor, itemTextColor },
  themeOptions,
  converter
) =>
  applyTextStyles({
    fontColor: itemFontColor || itemTextColor,
    fontWeight: itemFontWeight,
    fontSize: itemFontSize,
    lineHeight: scaleLineHeightRatio(converter, itemFontSize, itemLineHeight),
    fontName: itemFontName,
    themeOptions
  })

/**
 * Subcomponent used within ListItem and similar components for rendering content that fills
 * and wraps available space in a { flexDirection: row } container alongside a ListIconMark,
 * and that applies text styles to strings via supplied tokens.
 *
 * It's the responsibility of themes to make sure that these text tokens align the first line of
 * text nicely against the bullet or icon rendered by ListIconMark.
 */
export const ListItemContent = React.forwardRef(({ tokens, children }, ref) => {
  const { themeOptions } = useTheme()
  const converter = useFontScaleConverter()
  const textStyles = React.useMemo(
    () => selectItemTextStyles(tokens, themeOptions, converter),
    [tokens, themeOptions, converter]
  )
  return (
    <View
      style={[
        staticStyles.wrap,
        tokens?.itemUnderline && {
          textDecorationLine: tokens.itemUnderline,
          textDecorationColor: tokens.itemFontColor
        }
      ]}
      ref={ref}
    >
      {wrapStringsInText(children, { style: textStyles })}
    </View>
  )
})

ListItemContent.displayName = 'ListItemContent'

const staticStyles = StyleSheet.create({
  wrap: {
    flex: 1,
    justifyContent: 'center'
  }
})

ListItemContent.propTypes = {
  tokens: PropTypes.shape(tokenTypes).isRequired,
  children: PropTypes.node.isRequired
}
