import { HTMLAttributes, forwardRef } from 'react';
import { clsx } from 'clsx';
import { useMedia } from '../hooks/useMedia';
import { Breakpoint } from '../propsValues/breakpoint';

export type ShapeSize = 16 | 24 | 32 | 40 | 48 | 56 | 72;

export type Props = {
  /**
   * Modify underlying element, `div` by default
   */
  as?: React.ElementType;
  /**
   * Set size of the circle in px, `48` by default
   */
  size?: ShapeSize;
  /**
   * When `true` will use the fixed size (`48px`) instead of the CSS spacing variable (`--size-*`)
   * as those can be dynamic a at certain viewport sizes
   */
  fixedSize?: boolean;
  enableBorder?: boolean;
} & HTMLAttributes<HTMLDivElement>;

/**
 * circle like components has custom sizes for icons
 */
const MAP_ICON_SIZE = {
  16: 12,
  24: 16,
  32: 18,
  40: 20,
  48: 24,
  56: 28,
  72: 36,
};

/**
 * circle like components have custom typography styles for for default (Inter) font
 *
 * circle size : font size (px)
 */
const MAP_FONT_SIZE = {
  16: 8,
  24: 12,
  32: 14,
  40: 18,
  48: 22,
  56: 26,
  72: 30,
};

const Circle = forwardRef(function Circle(
  {
    as: Element = 'div',
    children,
    size = 48,
    fixedSize = false,
    enableBorder = false,
    className,
    style,
    ...props
  }: Props,
  ref,
) {
  const isTinyViewport = useMedia(`(max-width: ${Breakpoint.ZOOM_400}px)`);
  return (
    <Element
      {...props}
      ref={ref}
      style={{
        '--circle-size': fixedSize ? `${size}px` : `var(--size-${size})`,
        '--circle-icon-size':
          isTinyViewport && !fixedSize
            ? `${MAP_ICON_SIZE[size] / 2}px`
            : `${MAP_ICON_SIZE[size]}px`,
        '--circle-font-size': `${MAP_FONT_SIZE[size]}px`,
        ...style,
      }}
      className={clsx(
        'np-circle',
        { 'np-circle-border': enableBorder },
        'd-flex align-items-center justify-content-center',
        className,
      )}
    >
      {children}
    </Element>
  );
});

export default Circle;
