import React from 'react'
import PropTypes from 'prop-types'
import { getTokensPropType, selectSystemProps } from '@telus-uds/components-base'
import styled from 'styled-components'
import { htmlAttrs, useTypographyTheme } from '../utils'

const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])

const StyledSpan = styled.span`${({ flex }) => (flex ? 'display: inline-flex' : '')}};`

/**
 * Text as an HTML ```<span>``` element.
 *
 * Span may be used in cases where an inline span or direct access to HTML attributes is required.
 * In most cases, `Typography` should be used for text, or Paragraph for body text.
 */
const Span = React.forwardRef(({ children, variant, tokens, testID, flex, ...rest }, ref) => {
  const style = useTypographyTheme(variant, tokens)
  return (
    <StyledSpan data-testid={testID} flex={flex} style={style} ref={ref} {...selectProps(rest)}>
      {children}
    </StyledSpan>
  )
})

Span.displayName = 'Span'

Span.propTypes = {
  ...selectedSystemPropTypes,
  children: PropTypes.node.isRequired,
  /**
   * Adds `data-testid` attribute for testing
   */
  testID: PropTypes.string,
  /**
   * Sets display to inline-flex so that children are laid out using the flex model.
   * Use this if the span contains children that expect to be inside a flex container.
   */
  flex: PropTypes.bool,
  /**
   * Span takes the same tokens overrides as Typography
   */
  tokens: getTokensPropType('Typography'),
  /**
   * Span can take any of Typography's theme variants
   */
  variant: PropTypes.exact({
    bold: PropTypes.bool,
    colour: PropTypes.oneOf(['secondary', 'tertiary']),
    compact: PropTypes.bool,
    inverse: PropTypes.bool,
    size: PropTypes.oneOf([
      'micro',
      'small',
      'large',
      'eyebrow',
      'h1',
      'h2',
      'h3',
      'h4',
      'h5',
      'h6',
      'display1',
      'display2'
    ]),
    weight: PropTypes.oneOf(['semibold', 'bold'])
  })
}

export default Span
