import { EmojiType, IEmojiIcon } from '@vev/utils';
import { isObject, isString } from 'lodash';
import React, { HTMLAttributes } from 'react';
import { SilkeIconDefinitions } from '../../icons';
import styles from './silke-icon.scss';
import { SilkeShape } from './silke-shape';
import { SilkeColor } from '../../silke-theme-provider';

export type SilkeIcons = keyof typeof SilkeIconDefinitions | null | IEmojiIcon | `fa-${string}`;

interface SilkeIconProps extends HTMLAttributes<HTMLElement> {
  icon: SilkeIcons | React.ReactElement;
  color?: SilkeColor | string;
}

function isEmojiIcon(icon: SilkeIconProps['icon']): icon is IEmojiIcon {
  return isObject(icon) && 'type' in icon;
}

export function SilkeIcon({ icon, className, color, ...rest }: SilkeIconProps): JSX.Element {
  let cl = styles.icon;
  if (color) cl += ' ' + 'color-' + color;
  if (className) cl += ' ' + className;
  if (icon === 'ai.sparkle') cl += ' ' + styles.aiSparkle;
  if (React.isValidElement(icon)) {
    return (
      <span {...rest} className={cl}>
        {icon}
      </span>
    );
  }
  if (isString(icon) && /^https?:\/\//.test(icon)) {
    icon = { type: EmojiType.upload, value: { url: icon } };
  }

  if (isEmojiIcon(icon)) {
    switch (icon.type) {
      case EmojiType.icon:
        return <SilkeShape {...rest} className={cl} shape={icon.value} />;
      case EmojiType.upload:
        return <img {...rest} className={cl} src={icon.value.url} />;
    }

    cl += ' ' + styles.emoji;
    return (
      <span {...rest} className={cl}>
        {icon.value}
      </span>
    );
  }

  if (typeof icon === 'string' && icon.startsWith('fa-')) {
    return <i {...rest} className={cl + ' ' + icon} />;
  }

  if (!icon || !((icon as any) in SilkeIconDefinitions))
    return (
      <span {...rest} className={cl}>
        {icon}
      </span>
    );

  const Icon = SilkeIconDefinitions[icon as keyof typeof SilkeIconDefinitions];
  if (typeof Icon === 'string') return <i {...rest} className={cl + ' ' + Icon} />;

  return (
    <i {...rest} className={cl}>
      <Icon />
    </i>
  );
}
