import * as React from 'react';
import classNames from 'classnames';
import {generateId} from '../utils';

export type IconTypeType =
  | 'academic_cap'
  | 'achievement'
  | 'add_more'
  | 'ai'
  | 'all_questions'
  | 'answer_bubble'
  | 'answer'
  | 'answers'
  | 'apple'
  | 'archive_checked'
  | 'archive'
  | 'arrow_double_right'
  | 'arrow_down'
  | 'arrow_left'
  | 'arrow_right'
  | 'arrow_top_right'
  | 'arrow_up'
  | 'ask_bubble'
  | 'ask_parent_to_pay'
  | 'attachment'
  | 'autopublish'
  | 'bell_checked'
  | 'bell_outlined'
  | 'best_answer'
  | 'block'
  | 'bold'
  | 'brainly_oval'
  | 'brainly_parallelogram'
  | 'bulb_checked'
  | 'bulb_filled'
  | 'bulb'
  | 'bulleted_list'
  | 'calendar'
  | 'camera'
  | 'caret_down'
  | 'caret_up'
  | 'chapter'
  | 'chat'
  | 'check'
  | 'check_circle'
  | 'chevron_double_down'
  | 'chevron_double_right'
  | 'chevron_down'
  | 'chevron_left'
  | 'chevron_right'
  | 'chevron_up'
  | 'chevrons_horizontal'
  | 'circle'
  | 'clear'
  | 'clipboard'
  | 'clipboard_outlined'
  | 'close'
  | 'collapse'
  | 'comment_outlined'
  | 'comment'
  | 'counter'
  | 'credit_card'
  | 'crop'
  | 'crown_outlined'
  | 'crown'
  | 'cup'
  | 'cursor_select'
  | 'cyrillic'
  | 'discord'
  | 'document'
  | 'dot'
  | 'draw'
  | 'drawing_mode'
  | 'envelope'
  | 'equation'
  | 'eraser'
  | 'european'
  | 'exclamation_mark'
  | 'expand'
  | 'facebook'
  | 'filters'
  | 'forwad'
  | 'friend_add'
  | 'friend_checked'
  | 'friend_pending'
  | 'friend_remove'
  | 'friends'
  | 'fullscreen'
  | 'funnel'
  | 'ginny'
  | 'globe'
  | 'google'
  | 'graph'
  | 'greek'
  | 'heading'
  | 'heart_outlined'
  | 'heart'
  | 'highlight'
  | 'home'
  | 'how_to_scan'
  | 'image_library'
  | 'image'
  | 'influence'
  | 'info_outlined'
  | 'info'
  | 'instagram'
  | 'italic'
  | 'keyboard'
  | 'less'
  | 'line'
  | 'link'
  | 'linkedin'
  | 'lock_with_play'
  | 'logout'
  | 'math_scan'
  | 'medium'
  | 'megaphone'
  | 'menu'
  | 'message_new'
  | 'messages'
  | 'mic'
  | 'minimize'
  | 'mic_muted'
  | 'minus_in_circle_outlined'
  | 'money_transfer'
  | 'more'
  | 'multiselect_checked'
  | 'multiselect_unchecked'
  | 'notifications'
  | 'numbered_list'
  | 'open_in_new_tab'
  | 'options'
  | 'padlock_open'
  | 'padlock'
  | 'pause'
  | 'pdf'
  | 'pencil'
  | 'pi'
  | 'play'
  | 'plus'
  | 'points'
  | 'printer'
  | 'profile_settings'
  | 'profile_view'
  | 'profile'
  | 'question_alt'
  | 'question'
  | 'quote'
  | 'recent_questions_alt'
  | 'recent_questions'
  | 'rectangle'
  | 'reload'
  | 'report_flag_outlined'
  | 'report_flag'
  | 'rotate_90'
  | 'rotate'
  | 'search'
  | 'search_add'
  | 'seen'
  | 'send'
  | 'settings'
  | 'share'
  | 'shield'
  | 'sidebar_left'
  | 'sidebar_right'
  | 'smartphone'
  | 'sms'
  | 'spark'
  | 'sparks'
  | 'star_half_outlined'
  | 'star_half'
  | 'star_outlined'
  | 'star'
  | 'subtitle'
  | 'sup_sub'
  | 'symbols'
  | 'textbook'
  | 'thumb_down_outlined'
  | 'thumb_down'
  | 'thumb_up_outlined'
  | 'thumb_up'
  | 'title'
  | 'tiktok'
  | 'toughest_questions_alt'
  | 'toughest_questions'
  | 'trash'
  | 'triangle'
  | 'twitter'
  | 'underlined'
  | 'unseen'
  | 'upload'
  | 'user_block'
  | 'verified'
  | 'view_checked'
  | 'warning'
  | 'youtube'
  | 'gift';

export type IconColorType =
  | 'adaptive'
  | 'icon-black'
  | 'icon-white'
  | 'icon-blue-50'
  | 'icon-blue-60'
  | 'icon-indigo-50'
  | 'icon-indigo-60'
  | 'icon-green-50'
  | 'icon-green-60'
  | 'icon-yellow-50'
  | 'icon-yellow-60'
  | 'icon-red-50'
  | 'icon-red-60'
  | 'icon-gray-70'
  | 'icon-gray-60'
  | 'icon-gray-50'
  | 'icon-gray-40';

export type IconAsType = 'div' | 'span';
export type IconSizeType = 16 | 24 | 32 | 40 | 56 | 80 | 104;

export const TYPE = {
  ACADEMIC_CAP: 'academic_cap',
  ACHIEVEMENT: 'achievement',
  ADD_MORE: 'add_more',
  AI: 'ai',
  ALL_QUESTIONS: 'all_questions',
  ANSWER_BUBBLE: 'answer_bubble',
  ANSWER: 'answer',
  ANSWERS: 'answers',
  APPLE: 'apple',
  ARCHIVE_CHECKED: 'archive_checked',
  ARCHIVE: 'archive',
  ARROW_DOUBLE_RIGHT: 'arrow_double_right',
  ARROW_DOWN: 'arrow_down',
  ARROW_LEFT: 'arrow_left',
  ARROW_RIGHT: 'arrow_right',
  ARROW_TOP_RIGHT: 'arrow_top_right',
  ARROW_UP: 'arrow_up',
  ASK_BUBBLE: 'ask_bubble',
  ASK_PARENT_TO_PAY: 'ask_parent_to_pay',
  ATTACHMENT: 'attachment',
  AUTOPUBLISH: 'autopublish',
  BELL_CHECKED: 'bell_checked',
  BELL_OUTLINED: 'bell_outlined',
  BEST_ANSWER: 'best_answer',
  BLOCK: 'block',
  BOLD: 'bold',
  BRAINLY_OVAL: 'brainly_oval',
  BRAINLY_PARALLELOGRAM: 'brainly_parallelogram',
  BULB_CHECKED: 'bulb_checked',
  BULB_FILLED: 'bulb_filled',
  BULB: 'bulb',
  BULLETED_LIST: 'bulleted_list',
  CALENDAR: 'calendar',
  CAMERA: 'camera',
  CARET_DOWN: 'caret_down',
  CARET_UP: 'caret_up',
  CHAPTER: 'chapter',
  CHECK: 'check',
  CHAT: 'chat',
  CHECK_CIRCLE: 'check_circle',
  CHEVRON_DOUBLE_DOWN: 'chevron_double_down',
  CHEVRON_DOUBLE_RIGHT: 'chevron_double_right',
  CHEVRON_DOWN: 'chevron_down',
  CHEVRON_LEFT: 'chevron_left',
  CHEVRON_RIGHT: 'chevron_right',
  CHEVRON_UP: 'chevron_up',
  CHEVRONS_HORIZONTAL: 'chevrons_horizontal',
  CIRCLE: 'circle',
  CLEAR: 'clear',
  CLIPBOARD: 'clipboard',
  CLIPBOARD_OUTLINED: 'clipboard_outlined',
  CLOSE: 'close',
  COLLAPSE: 'collapse',
  COMMENT_OUTLINED: 'comment_outlined',
  COMMENT: 'comment',
  COUNTER: 'counter',
  CREDIT_CARD: 'credit_card',
  CROP: 'crop',
  CROWN_OUTLINED: 'crown_outlined',
  CROWN: 'crown',
  CUP: 'cup',
  CURSOR_SELECT: 'cursor_select',
  CYRILLIC: 'cyrillic',
  DOCUMENT: 'document',
  DOT: 'dot',
  DISCORD: 'discord',
  DRAW: 'draw',
  DRAWING_MODE: 'drawing_mode',
  ENVELOPE: 'envelope',
  EQUATION: 'equation',
  ERASER: 'eraser',
  EUROPEAN: 'european',
  EXCLAMATION_MARK: 'exclamation_mark',
  EXPAND: 'expand',
  FACEBOOK: 'facebook',
  FILTERS: 'filters',
  FORWARD: 'forward',
  FRIEND_ADD: 'friend_add',
  FRIEND_CHECKED: 'friend_checked',
  FRIEND_PENDING: 'friend_pending',
  FRIEND_REMOVE: 'friend_remove',
  FRIENDS: 'friends',
  FULLSCREEN: 'fullscreen',
  FUNNEL: 'funnel',
  GINNY: 'ginny',
  GLOBE: 'globe',
  GOOGLE: 'google',
  GRAPH: 'graph',
  GREEK: 'greek',
  HEADING: 'heading',
  HEART_OUTLINED: 'heart_outlined',
  HEART: 'heart',
  HIGHLIGHT: 'highlight',
  HOME: 'home',
  HOW_TO_SCAN: 'how_to_scan',
  IMAGE_LIBRARY: 'image_library',
  IMAGE: 'image',
  INFLUENCE: 'influence',
  INFO_OUTLINED: 'info_outlined',
  INFO: 'info',
  INSTRAGRAM: 'instagram',
  ITALIC: 'italic',
  KEYBOARD: 'keyboard',
  LESS: 'less',
  LINE: 'line',
  LINK: 'link',
  LINKEDIN: 'linkedin',
  LOCK_WITH_PLAY: 'lock_with_play',
  LOGOUT: 'logout',
  MATH_SCAN: 'math_scan',
  MEDIUM: 'medium',
  MEGAPHONE: 'megaphone',
  MENU: 'menu',
  MESSAGE_NEW: 'message_new',
  MESSAGES: 'messages',
  MIC: 'mic',
  MINIMIZE: 'minimize',
  MIC_MUTED: 'mic_muted',
  MINUS_IN_CIRCLE_OUTLIEND: 'minus_in_circle_outlined',
  MONEY_TRANSFER: 'money_transfer',
  MORE: 'more',
  MULTISELECT_CHECKED: 'multiselect_checked',
  MULTISELECT_UNCHECKED: 'multiselect_unchecked',
  NOTIFICATIONS: 'notifications',
  NUMBERED_LIST: 'numbered_list',
  OPEN_IN_NEW_TAB: 'open_in_new_tab',
  OPTIONS: 'options',
  PADLOCK_OPEN: 'padlock_open',
  PADLOCK: 'padlock',
  PAUSE: 'pause',
  PDF: 'pdf',
  PENCIL: 'pencil',
  PI: 'pi',
  PLAY: 'play',
  PLUS: 'plus',
  POINTS: 'points',
  PRINTER: 'printer',
  PROFILE_SETTINGS: 'profile_settings',
  PROFILE_VIEW: 'profile_view',
  PROFILE: 'profile',
  QUESTION_ALT: 'question_alt',
  QUESTION: 'question',
  QUOTE: 'quote',
  RECENT_QUESTIONS_ALT: 'recent_questions_alt',
  RECENT_QUESTIONS: 'recent_questions',
  RECTANGLE: 'rectangle',
  RELOAD: 'reload',
  REPORT_FLAG_OUTLINED: 'report_flag_outlined',
  REPORT_FLAG: 'report_flag',
  ROTATE_90: 'rotate_90',
  ROTATE: 'rotate',
  SEARCH: 'search',
  SEARCH_ADD: 'search_add',
  SEEN: 'seen',
  SEND: 'send',
  SETTINGS: 'settings',
  SHARE: 'share',
  SHIELD: 'shield',
  SIDEBAR_LEFT: 'sidebar_left',
  SIDEBAR_RIGHT: 'sidebar_right',
  SMARTPHONE: 'smartphone',
  SMS: 'sms',
  SPARK: 'spark',
  SPARKS: 'sparks',
  STAR_HALF_OUTLINED: 'star_half_outlined',
  STAR_HALF: 'star_half',
  STAR_OUTLINED: 'star_outlined',
  STAR: 'star',
  SUBTITLE: 'subtitle',
  SUP_SUB: 'sup_sub',
  SYMBOLS: 'symbols',
  TEXTBOOK: 'textbook',
  THUMB_DOWN_OUTLINED: 'thumb_down_outlined',
  THUMB_DOWN: 'thumb_down',
  THUMB_UP_OUTLINED: 'thumb_up_outlined',
  THUMB_UP: 'thumb_up',
  TITLE: 'title',
  TIKTOK: 'tiktok',
  TOUGHEST_QUESTIONS_ALT: 'toughest_questions_alt',
  TOUGHEST_QUESTIONS: 'toughest_questions',
  TRASH: 'trash',
  TRIANGLE: 'triangle',
  TWITTER: 'twitter',
  UNDERLINED: 'underlined',
  UNSEEN: 'unseen',
  UPLOAD: 'upload',
  USER_BLOCK: 'user_block',
  VERIFIED: 'verified',
  VIEW_CHECKED: 'view_checked',
  WARNING: 'warning',
  YOUTUBE: 'youtube',
  GIFT: 'gift',
} as const;

export const ICON_COLOR = {
  ADAPTIVE: 'adaptive',
  'icon-black': 'icon-black',
  'icon-white': 'icon-white',
  'icon-blue-50': 'icon-blue-50',
  'icon-blue-60': 'icon-blue-60',
  'icon-indigo-50': 'icon-indigo-50',
  'icon-indigo-60': 'icon-indigo-60',
  'icon-green-50': 'icon-green-50',
  'icon-green-60': 'icon-green-60',
  'icon-yellow-50': 'icon-yellow-50',
  'icon-yellow-60': 'icon-yellow-60',
  'icon-red-50': 'icon-red-50',
  'icon-red-60': 'icon-red-60',
  'icon-gray-70': 'icon-gray-70',
  'icon-gray-60': 'icon-gray-60',
  'icon-gray-50': 'icon-gray-50',
  'icon-gray-40': 'icon-gray-40',
} as const;

export const ICON_TAG_TYPE = {
  DIV: 'div',
  SPAN: 'span',
} as const;

export const SIZE = [16, 24, 32, 40, 56, 80, 104];
export type IconPropsType =
  | ({
      /**
       * Additional class names
       */
      className?: string | null | undefined;

      /**
       * Icons colors example, see more in SG interactive
       * @example <Icon color="icon-black" type="answer" />
       * @see color="adaptive" https://styleguide.brainly.com/latest/docs/interactive.html?color=adaptive#icons
       */
      color?: IconColorType | null | undefined;

      /**
       * Icons size example, see more in SG interactive
       * @example <Icon size="24" type="answer" />
       * @see size="24" https://styleguide.brainly.com/latest/docs/interactive.html?size=24#icons
       */
      size?: IconSizeType | null | undefined;

      /**
       * Icons types example, see more in SG interactive
       * @example <Icon size="24" type="answer" />
       * @see type="heart" https://styleguide.brainly.com/latest/docs/interactive.html?type=heart#icons
       */
      type: IconTypeType;

      /**
  * Option to change tag to span, which allows correct HTML structure
  * @example  <Button
                variant="secondary"
              >
                Get +50
                <Icon
                  type={iconTypes.POINTS}
                  color="dark"
                  size={16}
                  as="span"
                />
              </Button>
  */
      as?: IconAsType;

      /**
       * An accessible, short-text description; defaults to `type`
       */
      title?: string;

      /**
       * An accessible, long-text description
       */
      description?: string;
    } & Omit<
      React.AllHTMLAttributes<HTMLElement>,
      'className' | 'color' | 'size' | 'type' | 'as' | 'title' | 'description'
    >)
  | ({
      /**
       * Children to be rendered inside Icon
       */
      children: React.ReactNode;

      /**
       * Additional class names
       */
      className?: string | null | undefined;

      /**
       * Icons colors example, see more in SG interactive
       * @example <Icon color="icon-black" type="answer" />
       * @see color="adaptive" https://styleguide.brainly.com/latest/docs/interactive.html?color=adaptive#icons
       */
      color?: IconColorType | null | undefined;

      /**
       * Icons size example, see more in SG interactive
       * @example <Icon size="24" type="answer" />
       * @see size="24" https://styleguide.brainly.com/latest/docs/interactive.html?size=24#icons
       */
      size?: IconSizeType | null | undefined;

      /**
  * Option to change tag to span, which allows correct HTML structure
  * @example  <Button
                variant="secondary"
              >
                Get +50
                <Icon
                  type={iconTypes.POINTS}
                  color="dark"
                  size={16}
                  as="span"
                />
              </Button>
  */
      as?: IconAsType;

      /**
       * An accessible, short-text description; defaults to `type`
       */
      title?: string;

      /**
       * An accessible, long-text description
       */
      description?: string;
    } & Omit<
      React.AllHTMLAttributes<HTMLElement>,
      | 'children'
      | 'className'
      | 'color'
      | 'size'
      | 'as'
      | 'title'
      | 'description'
    >);

function generateIdSuffix(type: string) {
  return `${type}-${generateId()}`;
}

const Icon = ({
  color = ICON_COLOR['icon-white'],
  size = 24,
  type,
  children,
  as = 'div',
  className,
  title,
  description,
  ...props
}: IconPropsType) => {
  const iconClass = classNames(
    'sg-icon',
    {
      [`sg-icon--${String(color)}`]: color,
      [`sg-icon--x${String(size)}`]: size,
    },
    className
  );
  const iconType = `#icon-${type}`;
  const Tag = as;
  // @ts-ignore TS2345
  const idSuffix = generateIdSuffix(type);
  const titleId = `title-${idSuffix}`;
  const defaultTitle = String(type).replace(/_/g, ' ');
  const descId = `desc-${idSuffix}`;
  const labelledBy = description ? `${titleId} ${descId}` : titleId;
  const ariaLabel = type
    ? undefined
    : [title, description].filter(Boolean).join(', ');

  // suppressHydrationWarning is used until 'useId' hook is available
  return (
    <Tag {...props} className={iconClass} aria-label={ariaLabel}>
      {type ? (
        <svg
          className="sg-icon__svg"
          role="img"
          aria-labelledby={labelledBy}
          focusable="false"
          // fix for Property 'suppressHydrationWarning' does not exist on type 'SVGProps<SVGSVGElement>'
          {...{
            ...(React.version.startsWith('18') && {
              suppressHydrationWarning: true,
            }),
          }}
        >
          <text
            id={titleId}
            visibility="hidden"
            // fix for Property 'suppressHydrationWarning' does not exist on type 'SVGProps<SVGSVGTextElement>'
            {...{
              ...(React.version.startsWith('18') && {
                suppressHydrationWarning: true,
              }),
            }}
          >
            {title || defaultTitle}
          </text>
          {description && <desc id={descId}>{description}</desc>}
          <use xlinkHref={iconType} aria-hidden="true" />
        </svg>
      ) : (
        children
      )}
    </Tag>
  );
};

export default Icon;
