import { memo } from 'react';
import type { ReactNode } from 'react';
import clsx from 'clsx';

import { styled } from '@mui/material/styles';
import type { ClassNameMap } from '@mui/styles/withStyles';

import type { Theme } from '../@styles/theme-provider';

const StyledContainer = styled('div')(({ theme }: { theme: Theme }) => ({
  ...theme.typography.body2,
  position: 'relative',
  paddingLeft: theme.spacing(2),
  lineHeight: theme.spacing(2)
}));

type StyledIndicatorProps = {
  indicatorColor?: string;
};

const StyledIndicator = styled('span', {
  shouldForwardProp: prop => prop !== 'indicatorColor'
})<StyledIndicatorProps>(({ indicatorColor, theme }: StyledIndicatorProps & { theme: Theme }) => ({
  position: 'absolute',
  top: theme.spacing(0.5),
  left: 0,
  backgroundColor: indicatorColor,
  width: theme.spacing(1),
  height: theme.spacing(1),
  marginRight: theme.spacing(1),
  '&.square': {
    borderRadius: theme.spacing(1 / 8)
  },
  '&.circle': {
    borderRadius: '50%'
  }
}));

type StyledTextProps = {
  textColor?: string;
};

const StyledText = styled('span', {
  shouldForwardProp: prop => prop !== 'textColor'
})<StyledTextProps>(({ textColor, theme }: StyledTextProps & { theme: Theme }) => ({
  ...theme.typography.body2,
  color: textColor || theme.palette.primary[500],
  lineHeight: theme.spacing(2),
  pointerEvents: textColor === theme.palette.primary[100] ? 'none' : 'all'
}));

export interface TextWithIndicatorProps {
  /**
   * Components which will be rendered inside.
   */
  children: ReactNode;
  /**
   * The color of the square indicator.
   */
  indicatorColor: string;
  /**
   * Set shape of the indicator.
   */
  indicatorShape?: 'square' | 'circle';
  /**
   * Set shape of the indicator.
   */
  textColor?: string;
  /**
   * Custom class name in case you need to add custom styles to the component.
   */
  className?: string;
  /**
   * Override default classes.
   */
  classes?: Partial<ClassNameMap<'root' | 'indicator' | 'text'>>;
}

const TextWithIndicator = (props: TextWithIndicatorProps) => {
  const {
    children,
    indicatorColor,
    indicatorShape = 'square',
    textColor,
    classes,
    className
  } = props;

  return (
    <StyledContainer className={clsx(className, classes?.root)}>
      <StyledIndicator
        indicatorColor={indicatorColor}
        className={clsx(indicatorShape, classes?.indicator)}
      />
      <StyledText textColor={textColor} className={classes?.text}>
        {children}
      </StyledText>
    </StyledContainer>
  );
};

const m = memo(TextWithIndicator);
export { m as TextWithIndicator };
