import React from 'react'
import PropTypes from 'prop-types'
import { Platform, StyleSheet, View } from 'react-native'
import { variantProp } from '../utils/props/variantProp'
import { getTokensPropType } from '../utils/props/tokens'
import { useCopy } from '../utils/useCopy'
import { copyPropTypes } from '../utils/props/copyPropTypes'
import { a11yProps } from '../utils/props/a11yProps'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { IconButton } from '../IconButton/IconButton'
import { dictionary } from './dictionary'

// One layer above the overlapping tab so the button receives the tap.
const HORIZONTAL_SCROLL_BUTTON_LAYER = 1

const selectContainerStyles = ({ offset }) => ({
  marginTop: offset ? -offset : 0
})

/**
 * Button within a Tabs component showing users that content is available to the left or
 * right, scrolling a screen's worth of content left or right when pressed.
 *
 * This is rendered automatically by `Tabs` and isn't intended be used directly.
 *
 * @TODO when IconButton is complete and stable revisit this and update interaction state styles.
 */
export const HorizontalScrollButton = React.forwardRef(
  ({ direction = 'next', icon, offset, onPress, variant, tokens, copy, hitSlop }, ref) => {
    const themeTokens = useThemeTokens('HorizontalScrollButton', tokens, variant)
    const getCopy = useCopy({ dictionary, copy })
    const label = direction === 'previous' ? getCopy('previousText') : getCopy('nextText')

    return (
      <View
        style={[staticStyles.absolute, staticStyles[direction], selectContainerStyles({ offset })]}
      >
        <IconButton
          accessibilityLabel={label}
          icon={icon}
          onPress={onPress}
          ref={ref}
          tokens={themeTokens}
          variant={variant}
          hitSlop={hitSlop}
          {...a11yProps.nonFocusableProps}
        />
      </View>
    )
  }
)
HorizontalScrollButton.displayName = 'HorizontalScrollButton'

const staticStyles = StyleSheet.create({
  /*
   * `absolute` sits above the overlapping tab so the tap isn't captured by it. web/iOS use
   * zIndex; Android uses elevation (native layering that doesn't disturb the IconButton's own
   * shadow), matching ActivityIndicator/Carousel.
   */
  absolute: {
    position: 'absolute',
    ...Platform.select({
      android: { elevation: HORIZONTAL_SCROLL_BUTTON_LAYER },
      default: { zIndex: HORIZONTAL_SCROLL_BUTTON_LAYER }
    })
  },
  previous: {
    left: 0
  },
  next: {
    right: 0
  }
})

HorizontalScrollButton.propTypes = {
  tokens: getTokensPropType('HorizontalScrollButton'),
  variant: variantProp.propType,
  /**
   * Whether the English or French copy will be used (e.g. for accessibility labels).
   */
  copy: copyPropTypes,
  /**
   * Which edge the button sits on and the direction it scrolls: `'previous'` scrolls
   * content left, `'next'` scrolls content right
   */
  direction: PropTypes.oneOf(['previous', 'next']),
  /**
   * Vertical offset (in pixels) used to negate the container's `marginTop` so the button
   * aligns with the tab row
   */
  offset: PropTypes.number,
  /**
   * Icon element type rendered inside the underlying `IconButton`
   */
  icon: PropTypes.elementType,
  /**
   * Handler invoked when the button is pressed, scrolling one screen's worth of content
   */
  onPress: PropTypes.func.isRequired,
  /**
   * Additional distance (in pixels) outside the button's visual bounds that still
   * registers a press, forwarded to the underlying `IconButton`
   */
  hitSlop: PropTypes.number
}
