import { Animated } from 'react-native';
import type { ReactElement } from 'react';
import React, { useMemo } from 'react';
import { StyledView, StyledText, StyledIcon } from './StyledBadge';
import BadgeStatus from './Status';
import BadgeCount from './Count';
import type { BasicBadgeProps, IconBadgeProps } from './types';
import { DEFAULT_MAX_NUMBER } from './constants';

export type BadgeProps = BasicBadgeProps | IconBadgeProps;

const getPaddingState = (content: string): 'narrowContent' | 'wideContent' =>
  content.length > 1 ? 'wideContent' : 'narrowContent';

const Badge = ({
  content: originalContent,
  visible = true,
  max = DEFAULT_MAX_NUMBER,
  intent = 'danger',
  style,
  testID,
  size = 'medium',
  variant = 'filled',
  icon,
  ...nativeProps
}: BadgeProps): ReactElement => {
  const { current: opacity } = React.useRef<Animated.Value>(
    new Animated.Value(visible ? 1 : 0)
  );
  const isFirstRendering = React.useRef<boolean>(true);

  React.useEffect(() => {
    // Do not run animation on very first rendering
    if (isFirstRendering.current) {
      isFirstRendering.current = false;
      return;
    }

    Animated.timing(opacity, {
      toValue: visible ? 1 : 0,
      duration: 150,
      useNativeDriver: true,
    }).start();
  }, [visible, opacity]);

  const isIconBadge = !!icon;
  const isStringBadge = !isIconBadge && typeof originalContent === 'string';

  const content = useMemo(() => {
    if (isIconBadge) {
      return '';
    }
    return typeof originalContent === 'number' && originalContent > max
      ? `${max}+`
      : String(originalContent);
  }, [isIconBadge, originalContent, max]);

  return (
    <StyledView
      {...nativeProps}
      themeIntent={intent}
      themePadding={getPaddingState(content)}
      themeSize={size}
      themeVariant={variant}
      themeIsStringBadge={isStringBadge}
      style={[
        {
          opacity,
          transform: [
            {
              scale: opacity.interpolate({
                inputRange: [0, 1],
                outputRange: [0.5, 1],
              }),
            },
          ],
        },
        style,
      ]}
      testID={testID}
    >
      {isIconBadge ? (
        <StyledIcon icon={icon} themeSize={size} intent="text-inverted" />
      ) : (
        <StyledText
          themeSize={size}
          themeIntent={intent}
          themeIsStringBadge={isStringBadge}
        >
          {content}
        </StyledText>
      )}
    </StyledView>
  );
};

export default Object.assign(Badge, {
  Status: BadgeStatus,
  Count: BadgeCount,
});
