import * as React from 'react'
import * as PropTypes from 'prop-types'
import * as FeatherIcon from 'react-feather'
import styled from 'styled-components'
import { pascalCase, pascalCaseTransformMerge } from 'pascal-case'
import splitValueAndUnit from '../../services/splitValueAndUnit'

const Label = styled('span')({
  position: 'absolute',
  left: -999999,
  width: 1,
  height: 1,
  ':empty': {
    display: 'none',
  },
})

const StyledIcon = styled('svg')({
  stroke: 'currentColor',
  strokeLinecap: 'round',
  display: 'inline-block',
  verticalAlign: 'middle',
})

const propTypes = {
  /**
   * Name of the icon to display.
   */
  name: PropTypes.string.isRequired,
  /**
   * Width of the icon's strokes.
   */
  weight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  /**
   * Size of the icon. This controls both the width and the height.
   */
  size: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  /**
   * Describe of what the component represents.
   */
  label: PropTypes.string,
}

type Props = PropTypes.InferProps<typeof propTypes>

const Icon: React.FC<Props> = ({
  name,
  weight = '0.125rem',
  size = '1.5rem',
  label = name,
}) => {
  const iconName = pascalCase(name, { transform: pascalCaseTransformMerge })
  const { [iconName as keyof typeof FeatherIcon]: TheIcon = null } = FeatherIcon
  const { magnitude: sizeValue, unit: sizeUnit } = splitValueAndUnit(size)
  const { magnitude: weightValue } = splitValueAndUnit(weight)
  const factor = weightValue * (3 / 2)

  if (TheIcon !== null) {
    return (
      <span>
        <StyledIcon
          as={TheIcon}
          size={undefined}
          color={undefined}
          strokeLinecap={undefined}
          strokeWidth={undefined}
          style={{
            width: size!,
            height: size!,
            strokeWidth: `${factor / sizeValue}${sizeUnit}`,
          }}
          aria-label={label!}
        />
        <Label aria-hidden="true">{label}</Label>
      </span>
    )
  }

  return null
}

Icon.propTypes = propTypes

Icon.displayName = 'Icon'

export default Icon
