import React from 'react'
import PropTypes from 'prop-types'
import { View, StyleSheet, Platform, ScrollView } from 'react-native'
import { Portal } from '../Portal/Portal'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { Card } from '../Card/Card'

const staticStyles = StyleSheet.create({
  positioner: {
    flex: 1, // Grow to maxWidth when possible, shrink when not possible
    position: 'absolute',
    // Above every other overlay, and under INT32_MAX or native never paints it (#6341)
    zIndex: 1000000
  },
  hidden: {
    // Use opacity not visibility to hide the dropdown during positioning
    // so on web, children may be focused from the first render
    opacity: 0
  }
})

const paddingVertical = 0
const paddingHorizontal = 0

const DropdownOverlay = React.forwardRef(
  (
    {
      children,
      isReady = false,
      overlaidPosition,
      maxWidth,
      maxHeight,
      minWidth,
      onLayout,
      tokens,
      testID,
      variant
    },

    ref
  ) => {
    const systemTokens = useThemeTokens('Listbox', variant, tokens)

    return (
      <View
        ref={ref}
        onLayout={onLayout}
        testID={testID}
        style={[
          overlaidPosition,
          { maxWidth, minWidth },
          staticStyles.positioner,
          !isReady && staticStyles.hidden
        ]}
        onMouseDown={(e) => {
          e.preventDefault()
        }}
      >
        <Card
          tokens={{
            shadow: systemTokens.shadow,
            borderRadius: systemTokens.borderRadius,
            ...(Platform.OS === 'web' && {
              maxHeight,
              overflowY: 'auto'
            }),
            paddingBottom: paddingVertical,
            paddingTop: paddingVertical,
            paddingLeft: paddingHorizontal,
            paddingRight: paddingHorizontal
          }}
        >
          {Platform.OS !== 'web' ? (
            <ScrollView style={{ maxHeight }}>{children}</ScrollView>
          ) : (
            children
          )}
        </Card>
      </View>
    )
  }
)

const withPortal = (Overlay) => {
  // eslint-disable-next-line react/display-name, react/no-multi-comp
  return React.forwardRef((props, ref) => (
    <Portal>
      <Overlay {...props} ref={ref} />
    </Portal>
  ))
}

DropdownOverlay.displayName = 'DropdownOverlay'

DropdownOverlay.propTypes = {
  children: PropTypes.node.isRequired,
  isReady: PropTypes.bool,
  overlaidPosition: PropTypes.shape({
    top: PropTypes.number,
    left: PropTypes.number,
    width: PropTypes.number
  }),
  maxWidth: PropTypes.number,
  maxHeight: PropTypes.number,
  minWidth: PropTypes.number,
  onLayout: PropTypes.func,
  tokens: PropTypes.object,
  testID: PropTypes.string,
  variant: PropTypes.object
}

export const ListboxOverlay = Platform.OS === 'web' ? withPortal(DropdownOverlay) : DropdownOverlay
