import React from 'react'
import { Platform, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'

import { a11yProps } from '../utils/props/a11yProps'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { viewProps } from '../utils/props/viewProps'

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

/**
 * A11yText is a zero-size invisible element that adds text to be read by screen readers.
 *
 * It should be used to add selectable screen-reader-only text to the main document flow,
 * as a sibling to blocks of text like paragraphs and interactive elements like buttons.
 */
export const A11yText = React.forwardRef(({ text, heading, role = 'text', ...rest }, ref) => {
  const selectedProps = selectProps({
    // On iOS, needs `accessible` to be true to be focusable without non-a11y content.
    // On Web, `accessible` causes RNW to set attributes that may make the element be treated as a group.
    // On Android, may cause this to be skipped when with `<Text>` siblings in an `accessible` View,
    // see https://github.com/facebook/react-native/issues/30851#issuecomment-790165489
    accessible: Platform.OS === 'ios',
    accessibilityLabel: text,
    accessibilityRole: heading ? 'header' : role,
    ...rest
  })

  return <View style={styles.invisible} ref={ref} {...selectedProps} />
})

A11yText.displayName = 'A11yText'

A11yText.propTypes = {
  ...selectedSystemPropTypes,
  /**
   * Text to be read by screen readers
   */
  text: PropTypes.string.isRequired,
  /**
   * Whether text should be rendered as a heading
   */
  heading: PropTypes.bool,
  /**
   * Role of the element
   */
  role: PropTypes.string
}

const styles = StyleSheet.create({
  invisible: {
    // Without width or height it is not shown
    minHeight: 1,
    minWidth: 1,
    // Ensures it doesn't occupy space
    // position: 'absolute' causes it to be read first in its container
    marginEnd: -1,
    marginBottom: -1,
    // Ensures it is in the correct position on Native
    top: -1
  }
})
