import React from 'react'
import PropTypes from 'prop-types'
import { Platform } from 'react-native'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { useScrollBlocking } from '../utils/useScrollBlocking'
import { getTokensPropType } from '../utils/props/tokens'
import { variantProp } from '../utils/props/variantProp'

import { FullScreenIndicator } from './FullScreenIndicator'
import { OverlayIndicator } from './OverlayIndicator'
import { InlineIndicator } from './InlineIndicator'

const labelMapping = {
  top: 'column-reverse',
  bottom: 'column',
  left: 'row-reverse',
  right: 'row'
}

/**
 * `ActivityIndicator` renders a visual loading state.
 * It does not handle positioning or layout of that visual loader.
 */
export const ActivityIndicator = React.forwardRef(
  (
    {
      variant,
      tokens,
      label,
      labelPosition = 'bottom',
      showLabel = true,
      inline = false,
      fullScreen = false,
      overlay = false,
      isStatic = false,
      children,
      fullScreenBackgroundColor
    },
    ref
  ) => {
    const {
      size,
      dotSize,
      color,
      indicatorBackgroundColor,
      fullScreenOverlayBackground,
      thickness
    } = useThemeTokens('ActivityIndicator', tokens, variant)

    useScrollBlocking([Platform.OS === 'web' && fullScreen])

    const variantProps = {
      variant,
      dotSize,
      size,
      color,
      indicatorBackgroundColor,
      thickness,
      isStatic
    }

    const visibleLabel = showLabel && !!label

    const commonProps = {
      ref,
      variantProps,
      label,
      labelPosition,
      labelMapping,
      showLabel: visibleLabel
    }

    switch (true) {
      case fullScreen:
        return (
          <FullScreenIndicator
            {...commonProps}
            backgroundColor={fullScreenBackgroundColor || fullScreenOverlayBackground}
          />
        )

      case overlay:
        return (
          <OverlayIndicator {...commonProps} inline={inline} isActive={overlay}>
            {children}
          </OverlayIndicator>
        )

      default:
        return <InlineIndicator {...commonProps} />
    }
  }
)

ActivityIndicator.displayName = 'ActivityIndicator'

ActivityIndicator.propTypes = {
  variant: variantProp.propType,
  tokens: getTokensPropType('ActivityIndicator'),
  /**
   * A visually hidden accessible label describing the action taking place
   */
  label: PropTypes.string,
  /**
   * If true, it should render a static ActivityIndicator
   */
  isStatic: PropTypes.bool,
  /**
   * Position of the label relative to ActivityIndicator
   */
  labelPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
  /**
   * show or hide the label
   */
  showLabel: PropTypes.bool,
  /**
   * If true, the ActivityIndicator will be displayed in full screen mode
   */
  fullScreen: PropTypes.bool,
  /**
   * If true, the ActivityIndicator will be displayed inline
   */
  inline: PropTypes.bool,
  /**
   * If true, the ActivityIndicator will be displayed in overlay mode
   */
  overlay: PropTypes.bool,
  /**
   * Children to be rendered inside ActivityIndicator
   */
  children: PropTypes.node,
  /**
   * Background color of the full screen overlay
   */
  fullScreenBackgroundColor: PropTypes.string
}
