import React from 'react'
import PropTypes from 'prop-types'
import {
  Icon,
  useResponsiveProp,
  useThemeTokens,
  Listbox,
  getTokensPropType
} from '@telus-uds/components-base'
import NavigationItem from './NavigationItem'
import useOverlaidPosition from '../utils/useOverlaidPosition'
import resolveItemSelection from './resolveItemSelection'

const MIN_WIDTH = 192
const MAX_WIDTH = 289
const DEFAULT_OFFSETS = { offsets: { vertical: 4 } }
const XS_ALIGN = { top: 'bottom', left: 'left' }
const SM_ALIGN = { top: 'bottom', right: 'right' }
const LG_ALIGN = { top: 'bottom', center: 'center' }

const getResponsiveBreakpoints = (sourceWidth) => ({
  xs: {
    ...DEFAULT_OFFSETS,
    align: XS_ALIGN,
    minWidth: sourceWidth,
    maxWidth: sourceWidth
  },
  sm: {
    ...DEFAULT_OFFSETS,
    align: SM_ALIGN,
    minWidth: sourceWidth,
    maxWidth: sourceWidth
  },
  lg: {
    ...DEFAULT_OFFSETS,
    align: LG_ALIGN,
    minWidth: MIN_WIDTH,
    maxWidth: MAX_WIDTH
  }
})

/**
 * A NavigationItem that opens or closes a Listbox of other NavigationItems.
 *
 * This is rendered automatically by `NavigationBar` and isn't intended be used directly.
 */
const NavigationSubMenu = React.forwardRef(
  (
    {
      children,
      id,
      isOpen = false,
      tokens = {},
      variant = {},
      label,
      onClick,
      selectedId,
      items = [],
      openOverlayRef,
      LinkRouter,
      linkRouterProps,
      itemsContainerRef
    },
    ref
  ) => {
    const focusTrapRef = React.useRef()
    const [sourceWidth, setSourceWidth] = React.useState(0)

    const { align, offsets, minWidth, maxWidth } = useResponsiveProp(
      getResponsiveBreakpoints(sourceWidth)
    )

    const { overlaidPosition, sourceRef, targetRef, onTargetLayout, isReady } = useOverlaidPosition(
      {
        isShown: isOpen,
        offsets,
        align
      }
    )
    const { selected } = resolveItemSelection({ id, label, items }, selectedId)

    const handleClick = (event) => {
      if (typeof onClick === 'function') onClick(event)
    }

    const { icoMenu } = useThemeTokens('NavigationBar', tokens, {}, { expanded: isOpen })

    React.useEffect(() => {
      sourceRef.current?.measureInWindow((_, __, width) => {
        setSourceWidth(width)
      })
    }, [isOpen, sourceRef])

    return (
      <>
        <NavigationItem
          ref={sourceRef}
          accessibilityRole="button"
          id={id}
          selected={selected}
          onClick={handleClick}
          icon={icoMenu}
          tokens={tokens}
        >
          {({ textStyles }) => [
            children,
            <Icon
              key={`${id}_icon`}
              icon={icoMenu}
              variant={{ size: 'micro' }}
              tokens={{ color: textStyles[0]?.color }}
            />
          ]}
        </NavigationItem>
        {isOpen && (
          <>
            <Listbox.Overlay
              overlaidPosition={overlaidPosition}
              maxWidth={maxWidth}
              minWidth={minWidth}
              isReady={isReady}
              onLayout={onTargetLayout}
              ref={openOverlayRef}
              variant={variant}
            >
              <Listbox
                items={items}
                firstItemRef={targetRef}
                parentRef={sourceRef}
                selectedId={selectedId}
                LinkRouter={LinkRouter}
                linkRouterProps={linkRouterProps}
                variant={variant}
                ref={itemsContainerRef || ref}
              />
            </Listbox.Overlay>
            <div
              // This catches and shifts focus to other interactive elements.
              // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
              tabIndex={0}
              ref={focusTrapRef}
              onFocus={() => targetRef.current.focus()}
            />
          </>
        )}
      </>
    )
  }
)

NavigationSubMenu.displayName = 'NavigationSubMenu'

// @TODO - proper prop types and comments
NavigationSubMenu.propTypes = {
  tokens: getTokensPropType('NavigationBar'),
  children: PropTypes.node,
  id: PropTypes.string,
  isOpen: PropTypes.bool,
  label: PropTypes.string,
  onClick: PropTypes.func,
  selectedId: PropTypes.string,
  items: PropTypes.array,
  openOverlayRef: PropTypes.object,
  LinkRouter: PropTypes.elementType,
  linkRouterProps: PropTypes.object,
  itemsContainerRef: PropTypes.object,
  variant: PropTypes.object
}

export default NavigationSubMenu
