import React from 'react'
import PropTypes from 'prop-types'
import { useTheme } from '../ThemeProvider/useTheme'
import { ResponsiveProp } from './ResponsiveProp'
import { ResponsiveWithMediaQueryStyleSheet } from './ResponsiveWithMediaQueryStyleSheet'

/**
 * Responsive conditionally renders children based on whether the viewport matches the provided
 * min and max viewports.
 *
 * If enableMediaQueryStyleSheet themeOption is set to false in ThemeProvider, then in SSR,
 * like other viewport utilities, it treats the viewport as `xs` both in SSR itself and
 * during first hydration on the client side; then if the viewport is not `xs`, it re-renders
 * after hydration. This may cause a layout shift on devices other than the narrowest.
 *
 * If enableMediaQueryStyleSheet themeOption is set to true in ThemeProvider, then a media query
 * stylesheet hides and shows the children of `Responsive` within a View. That View is a host element
 * in the tree, and the children mount at every viewport rather than only the ones in range. See
 * `ResponsiveWithMediaQueryStyleSheet` for what those two differences mean for a consumer.
 */

export const Responsive = React.forwardRef(
  ({ min = 'xs', max, inheritedStyles = [], children }, ref) => {
    const {
      themeOptions: { enableMediaQueryStyleSheet }
    } = useTheme()
    if (enableMediaQueryStyleSheet) {
      return (
        <ResponsiveWithMediaQueryStyleSheet
          inheritedStyles={inheritedStyles}
          min={min}
          max={max}
          ref={ref}
        >
          {children}
        </ResponsiveWithMediaQueryStyleSheet>
      )
    }
    return (
      <ResponsiveProp min={min} max={max}>
        {children}
      </ResponsiveProp>
    )
  }
)

Responsive.displayName = 'Responsive'

Responsive.propTypes = {
  /**
   * To hide children of `Responsive` if the current viewport is smaller than `min`
   */
  min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
  /**
   * To hide children of `Responsive` if the current viewport is larger than `max`
   */
  max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
  /**
   * Styles to be inherited by `Responsive`.
   * It should be an array of style property names.
   * Note: This prop is only applicable when `enableMediaQueryStyleSheet` is set to true in the `ThemeProvider`.
   */
  inheritedStyles: PropTypes.arrayOf(PropTypes.string),
  /**
   * Content rendered only at the matching viewports.
   */
  children: PropTypes.node.isRequired
}
