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

import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { a11yProps } from '../utils/props/a11yProps'
import { getTokensPropType } from '../utils/props/tokens'
import { selectSystemProps } from '../utils/props/selectSystemProps'
import { useMultipleInputValues } from '../utils/input'
import { variantProp } from '../utils/props/variantProp'
import { viewProps } from '../utils/props/viewProps'
import { contentfulProps } from '../utils/props/contentfulProps'
import { useUniqueId } from '../utils/useUniqueId'

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

const selectWrapperStyles = ({ borderWidth, borderTopWidth, borderStyle, borderColor }) => ({
  borderStyle,
  borderColor,
  borderTopWidth,
  borderBottomWidth: borderWidth,
  borderBottomStyle: borderStyle,
  borderBottomColor: borderColor
})

/**
 * Flexible base component for lists where some or all items are collapsible headers.
 *
 * Pass a render function as `children` which takes and passes `openIds` and `onToggle` props to
 * <ExpandCollapsePanel> children, and assign the panels explicit `panelId` props. The panels may be
 * nested (they do not need to be direct children), and non-interactive items may be included too.
 */
export const ExpandCollapse = React.forwardRef(
  ({ children, tokens, variant, maxOpen, open, initialOpen, onChange, dataSet, ...rest }, ref) => {
    const instanceId = useUniqueId('ExpandCollapse')

    const {
      currentValues: openIds,
      toggleOneValue: onToggle,
      resetValues,
      setValues,
      unsetValues
    } = useMultipleInputValues({
      maxValues: maxOpen,
      values: open,
      initialValues: initialOpen,
      onChange
    })
    const themeTokens = useThemeTokens('ExpandCollapse', tokens, variant)

    return (
      <View style={staticStyles.container} ref={ref} {...selectProps(rest)} dataSet={dataSet}>
        <View style={selectWrapperStyles(themeTokens)}>
          {typeof children === 'function'
            ? children({ openIds, onToggle, resetValues, setValues, unsetValues, instanceId })
            : children}
        </View>
      </View>
    )
  }
)
ExpandCollapse.displayName = 'ExpandCollapse'

ExpandCollapse.propTypes = {
  ...selectedSystemPropTypes,
  variant: variantProp.propType,
  tokens: getTokensPropType('ExpandCollapse'),
  /**
   * ExpandCollapse usually takes a render function to which it passes an object with properties
   * { openIds, onToggle, resetValues, setValues, unsetValues }. openIds (array of ids) and
   * onToggle (function) will usually be passed to `<ExpandCollapsePanel>`
   */
  children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]).isRequired,
  /**
   * If set, enforces a specific maximum number of open items, closing already-open items when new
   * items are opened. By default, any number of items may be open at once.
   */
  maxOpen: PropTypes.number,
  /**
   * If passed, the item or items that are expanded will be controlled by a parent component
   */
  open: PropTypes.arrayOf(PropTypes.string),
  /**
   * Function called when which panels are currently open changes. Necessary if `open` is passed.
   */
  onChange: PropTypes.func,
  /**
   * Allows items with specified ids to be open by default on first load. Should not be used with `open`.
   */
  initialOpen: PropTypes.arrayOf(PropTypes.string)
}

const staticStyles = StyleSheet.create({
  container: {
    display: 'flex'
  }
})
