import React, { FunctionComponent, forwardRef } from "react";
import classNames from "classnames";
import { JUSTIFY, ORIENTATION, Spacing } from "../../types";
import { bem } from "../../utilities";
import { Flex } from "../Flex";
import { BoxProps } from "../Box";

const cn = "Stack";

export interface StackProps extends BoxProps {
  /**
   * Orientation uses an enum whose value can be "horizontal"
   * (default) or "vertical"
   */
  orientation?: ORIENTATION;
  /**
   * Determines how much spacing is placed between the items; 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.
   *
   * See [spacing tokens](/?path=/docs/tokens-spacing--page).
   */
  spacing?: Spacing;
  /**
   * Using flexbox's [justify-content attribute](https://css-tricks.com/almanac/properties/j/justify-content/),
   * this prop spaces the items accordingly. Valid values from the enum
   * include "around", "between", "center", "end" or "start" (default).
   * This prop only works when orientation is set to "horizontal".
   */
  justify?: JUSTIFY;
  /**
   * Reverse the order of the controls; only works when orientation is
   * "horizontal". This allows for a primary action to be placed after a
   * secondary action _visually_, but keeps the primary action first in
   * the source order, which is helpful when tabbing through controls (
   * i.e., tab from right to left).
   */
  reverse?: boolean;
}

export const Stack: FunctionComponent<StackProps> = forwardRef<
  HTMLDivElement,
  StackProps
>(
  (
    {
      className,
      orientation = ORIENTATION.HORIZONTAL,
      spacing = 2,
      justify = JUSTIFY.START,
      reverse = false,
      children,
      ...rest
    },
    ref,
  ) => {
    return (
      <Flex
        ref={ref}
        className={classNames([
          bem(cn, { m: orientation }),
          spacing > 0 && bem(cn, { m: `spacing-${spacing}` }),
          reverse && bem(cn, { m: "reverse" }),
          `justify-${justify}`,
          className,
        ])}
        {...rest}
      >
        {children}
      </Flex>
    );
  },
);
