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

import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { getTokensPropType } from '../utils/props/tokens'
import { variantProp } from '../utils/props/variantProp'

export const Icon = React.forwardRef(
  (
    {
      icon: IconComponent,
      accessibilityLabel,
      variant,
      tokens,
      scalesWithText = false,
      style = {},
      testID,
      dataSet
    },
    ref
  ) => {
    const themeTokens = useThemeTokens('Icon', tokens, variant)
    const { fontScale } = useWindowDimensions()

    const size = scalesWithText ? themeTokens.size * fontScale : themeTokens.size

    const iconContent = (
      <IconComponent
        title={accessibilityLabel}
        size={size}
        color={themeTokens.color}
        gradient={themeTokens.gradient}
      />
    )

    const paddingStyles = variant?.padding
      ? {
          padding: themeTokens.width,
          width: themeTokens.size + themeTokens.width * 2, // sets the diameter of the circle which is the size of the icon plus twice the general padding established to obtain a perfect circle
          height: themeTokens.size + themeTokens.width * 2
        }
      : {
          padding: themeTokens.padding
        }

    const getIconContentForMobile = () => {
      return (
        <View
          testID={testID}
          style={{
            backgroundColor: themeTokens.backgroundColor,
            borderRadius: themeTokens.borderRadius,
            ...paddingStyles
          }}
        >
          {iconContent}
        </View>
      )
    }

    return Platform.OS === 'web' ? (
      <View
        testID={testID}
        ref={ref}
        // eslint-disable-next-line react-native/no-inline-styles
        style={{
          // TODO: systematise animations.
          // https://github.com/telus/universal-design-system/issues/487
          transition: 'transform 200ms, color 200ms',
          transform: [
            themeTokens.scale ? `scale(${themeTokens.scale})` : '',
            themeTokens.translateX ? `translateX(${themeTokens.translateX}px)` : '',
            themeTokens.translateY ? `translateY(${themeTokens.translateY}px)` : ''
          ]
            .filter((exists) => exists)
            .join(' '),
          ...style,
          backgroundColor: themeTokens.backgroundColor,
          borderRadius: themeTokens.borderRadius,
          paddingTop: themeTokens.paddingTop,
          ...paddingStyles
        }}
        dataSet={dataSet}
      >
        {iconContent}
      </View>
    ) : (
      getIconContentForMobile()
    )
  }
)
Icon.displayName = 'Icon'

export const iconComponentPropTypes = {
  variant: variantProp.propType,
  tokens: getTokensPropType('Icon'),
  /**
   * Descriptive label used in web SVG title tag for accessibility
   */
  accessibilityLabel: PropTypes.string,
  /**
   * controls whether the icon size should be proportionate to any accessibility-related font scaling.
   */
  scalesWithText: PropTypes.bool,
  /**
   * Custom style object to be applied to the icon component.
   * This is useful for overriding the default icon style but for cases where desires styles are not available as tokens.
   *
   * Note: This prop is only used in web.
   *
   * @example
   * <Icon style={{ color: 'red' }}
   */
  style: PropTypes.object
}

Icon.propTypes = {
  ...iconComponentPropTypes,
  /**
   * A valid UDS icon component imported from a UDS palette
   * (e.g.) `import { MyIcon } from @telus-uds/palette-<brand>/build/web/icons`
   */
  icon: PropTypes.elementType.isRequired
}
