import React from 'react'
import { View, Platform, StyleSheet } from 'react-native'
import PropTypes from 'prop-types'
import { a11yProps } from '../utils/props/a11yProps'
import { getTokensPropType } from '../utils/props/tokens'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { variantProp } from '../utils/props/variantProp'
import { viewProps } from '../utils/props/viewProps'
import { ListItemContent } from './ListItemContent'
import { ListItemMark } from './ListItemMark'
import { Typography } from '../Typography/Typography'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])

const VERTICAL_CENTERING_DIVISOR = 2

const alignmentMap = {
  top: 'flex-start',
  center: 'center',
  bottom: 'flex-end'
}

const selectItemBlockStyles = ({ interItemMargin }) => ({
  marginBottom: interItemMargin
})

const selectDividerStyles = ({ dividerColor, dividerSize, interItemMarginWithDivider }) => ({
  borderBottomWidth: dividerSize,
  borderColor: dividerColor,
  marginBottom: interItemMarginWithDivider,
  paddingBottom: interItemMarginWithDivider
})

const selectAlignmentStyles = (iconVerticalAlign) => ({
  alignItems: alignmentMap[iconVerticalAlign]
})

/**
 * ListItem is responsible for rendering icon or a bullet as side item
 */
const calculateIconMarginTop = (itemIconSize, fontSize, lineHeightRatio) => {
  return (fontSize * lineHeightRatio - itemIconSize) / VERTICAL_CENTERING_DIVISOR
}

export const ListItemBase = React.forwardRef(
  (
    {
      tokens,
      icon,
      iconColor,
      iconSize,
      showDivider,
      children,
      title,
      isLastItem,
      iconVerticalAlign = 'top',
      accessibilityRole = Platform.select({ web: 'listitem', default: undefined }),
      ...rest
    },
    ref
  ) => {
    const themeTokens = typeof tokens === 'function' ? tokens() : tokens

    const itemBlockStyles = selectItemBlockStyles(themeTokens)
    const dividerStyles = selectDividerStyles(themeTokens)
    const { iconMarginTop, itemIconSize } = themeTokens
    const { fontSize, lineHeight: lineHeightRatio } = useThemeTokens(
      'Typography',
      {},
      { size: 'h4', bold: true }
    )
    const adjustedIconMarginTop = title
      ? calculateIconMarginTop(itemIconSize, fontSize, lineHeightRatio)
      : iconMarginTop

    /**
     * Function responsible returning styling, in case the item is the last shouldn't
     * add extra margin on the bottom, if "showDivider" is true it should add a divider
     * and custom margin and padding, otherwise just adds a margin to the bottom
     */
    const getContainerStyle = () => {
      if (isLastItem) {
        return undefined
      }

      if (showDivider) {
        return dividerStyles
      }

      return itemBlockStyles
    }

    return (
      <View
        ref={ref}
        style={[staticStyles.container, getContainerStyle()]}
        accessibilityRole={accessibilityRole}
        {...selectProps(rest)}
      >
        {typeof children === 'function' ? (
          children({ tokens, icon, iconColor, iconSize, isLastItem })
        ) : (
          <View style={[staticStyles.innerContainer, selectAlignmentStyles(iconVerticalAlign)]}>
            <ListItemMark
              tokens={{ ...tokens, iconMarginTop: adjustedIconMarginTop }}
              icon={icon}
              iconColor={iconColor}
              iconSize={iconSize}
            />
            <View style={[staticStyles.titleAndContentContainer]}>
              {Boolean(title) && (
                <Typography variant={{ size: 'h4', bold: true }}>{title}</Typography>
              )}
              <ListItemContent tokens={tokens}>{children}</ListItemContent>
            </View>
          </View>
        )}
      </View>
    )
  }
)
ListItemBase.displayName = 'ListItem'
ListItemBase.__UDS_COMPONENT_TYPE__ = 'ListItem'

const staticStyles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    width: '100%'
  },
  innerContainer: {
    flex: 1,
    flexDirection: 'row'
  },
  titleAndContentContainer: {
    flexDirection: 'column',
    flex: 1,
    flexGrow: 1,
    flexShrink: 1
  }
})

ListItemBase.propTypes = {
  ...selectedSystemPropTypes,
  tokens: getTokensPropType('List'),
  variant: variantProp.propType,
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  /** Controls the vertical alignment of the icon */
  iconVerticalAlign: PropTypes.oneOf(['top', 'center', 'bottom']),
  /**
   * Renders side item icon
   */
  icon: PropTypes.elementType,
  /**
   * Will set display icon color
   */
  iconColor: PropTypes.string,
  /**
   * Allow the user define the icon size if not defined the theme's file
   */
  iconSize: PropTypes.number,
  /**
   * @ignore
   * Defined by parent if it's last item on the list
   */
  isLastItem: PropTypes.bool,
  /**
   * @ignore
   * In case it is not the last item allow display divider
   */
  showDivider: PropTypes.bool
}
