import React, { ForwardRefExoticComponent, forwardRef } from "react";
import classNames from "classnames";
import { Box, BoxProps } from "../Box";

interface GridProps extends BoxProps {
  columns?: string[];
  rows?: string[];
  gap?: string;
}

interface GridItemProps extends BoxProps {
  column?: string;
  row?: string;
  area?: string;
}

export type GridWithItem = ForwardRefExoticComponent<GridProps> & {
  Item: (props: GridItemProps) => JSX.Element | null;
};

export const GridItem: ForwardRefExoticComponent<GridItemProps> = forwardRef<
  HTMLDivElement,
  GridItemProps
>((props, ref) => {
  const {
    className,
    style,
    column: gridColumn,
    row: gridRow,
    area: gridArea,
    ...rest
  } = props;

  /**
   * The compiler combines grid-column and grid-row into grid-area.
   * If we don’t check for a custom grid-area first, then grid-columns
   * and grid-rows don’t get applied.
   */
  const styles = gridArea
    ? {
        gridArea,
        ...style,
      }
    : {
        gridColumn,
        gridRow,
        ...style,
      };

  return <Box className={className} ref={ref} style={styles} {...rest} />;
});

export const Grid = forwardRef<HTMLDivElement, GridProps>((props, ref) => {
  const { className, style, columns = [], rows = [], gap, ...rest } = props;

  const styles = {
    gridTemplateColumns: columns.join(" "),
    gridTemplateRows: rows.join(" "),
    gap,
    ...style,
  };

  return (
    <Box
      className={classNames("grid", className)}
      ref={ref}
      style={styles}
      {...rest}
    />
  );
}) as GridWithItem;

Grid.Item = GridItem;
