import React, { ReactElement } from 'react';
import css from '../../utils/css';

import { CommonProps } from '../common';
import {
  IconWrapper,
  SpinningIcon,
  SpinningIconWrapper,
  StyledIcon,
} from './StyledIcon';
import './style.css';
import IconList from './IconList';

type IconName = typeof IconList[number];
type IconIntent =
  | 'inherit'
  | 'text'
  | 'subdued-text'
  | 'disabled-text'
  | 'primary'
  | 'info'
  | 'danger'
  | 'warning'
  | 'success'
  | 'error';

interface IconProps extends CommonProps {
  /**
   * Icon name or a custom icon as a react element.
   */
  icon: IconName | ReactElement;
  /**
   * Visual intent color to apply to icon, it will inherit from its parents' color by default.
   */
  intent?:
    | 'inherit'
    | 'text'
    | 'subdued-text'
    | 'disabled-text'
    | 'info'
    | 'primary'
    | 'danger'
    | 'warning'
    | 'success'
    | 'error';
  /**
   * Icon size, it will inherit from its parents' font-size by default. If you use custom icon, inherit will be changed to medium size.
   */
  size?: 'inherit' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
  /**
   * Rotate icon with animation.
   */
  spin?: boolean;
}

const Icon = ({
  icon,
  size = 'inherit',
  intent = 'inherit',
  spin = false,
  id,
  className,
  style,
  sx = {},
  'data-test-id': dataTestId,
}: IconProps): ReactElement => {
  const isCustomIcon = React.isValidElement(icon);
  const themeSize =
    isCustomIcon === true && size === 'inherit' ? 'medium' : size;
  const themeColor = intent;

  // Custom icon
  if (isCustomIcon) {
    const WrapperComponent = spin === true ? SpinningIconWrapper : IconWrapper;
    return (
      <WrapperComponent
        themeSize={themeSize}
        themeColor={themeColor}
        id={id}
        className={className}
        style={{ ...style, ...css(sx) }}
        data-test-id={dataTestId}
      >
        {icon}
      </WrapperComponent>
    );
  }

  const IconComponent = spin === true ? SpinningIcon : StyledIcon;

  return (
    <IconComponent
      id={id}
      className={
        className !== undefined
          ? `hero-icon-${icon} ${className}`
          : `hero-icon-${icon}`
      }
      style={{ ...style, ...css(sx) }}
      data-test-id={dataTestId}
      themeSize={themeSize}
      themeColor={themeColor}
    />
  );
};

Icon.List = IconList;

export { IconProps, IconName, IconIntent };

export default Icon;
