import React, {
  Children,
  ReactNode,
  ReactElement,
  isValidElement,
} from "react";
import classNames from "classnames";

import { bemHOF } from "../../utilities/bem";
import { Spacing } from "../../types";
import { BoxProps } from "../Box";
import { Flex } from "../Flex";

import { AvatarSize } from "./types";
import { AvatarContext } from "./context";

const cn = bemHOF("AvatarGroup");

export interface AvatarGroupProps extends BoxProps {
  /**
   * Avatar components
   */
  children: ReactNode[];
  /**
   * Determines how much spacing is placed between the avatars; the
   * values map to the padding values in the tailwind.config file, which
   * are a multiple of 4. 2 is the default value, i.e., 8px of spacing.
   *
   * There is also an optional “overlap” value which will add a negative
   * margin to each avatar to overlap them on top of each other. This
   * margin value is automatically calculated relative to the avatar
   * size.
   *
   * See [spacing tokens](/?path=/docs/tokens-spacing--page).
   */
  spacing?: "overlap" | Spacing;
  /**
   * Overrides the size prop on each Avatar within the group
   */
  size?: AvatarSize;
}

export const AvatarGroup = ({
  children,
  spacing = 0,
  size = "medium",
  className,
  ...rest
}: AvatarGroupProps) => {
  const validChildren = Children.toArray(children).filter((child) =>
    isValidElement(child),
  ) as ReactElement[];
  const reversedChildren = validChildren.reverse();

  return (
    <Flex
      className={classNames(
        cn(),
        spacing === "overlap" ? cn({ m: "overlap" }) : `gap-${spacing}`,
        className,
      )}
      {...rest}
    >
      <AvatarContext.Provider value={{ size }}>
        {reversedChildren}
      </AvatarContext.Provider>
    </Flex>
  );
};
