import React, { forwardRef, useContext } from "react";
import classNames from "classnames";
import { StyledProps } from "../_type";
import { useConfig } from "../_util/config-context";

export interface RowProps extends StyledProps {
  /**
   * 列之间的间隙
   * @default 20
   */
  gap?: number;

  /**
   * 栅格对齐方式，不传则栅格等高
   */
  verticalAlign?: "top" | "middle" | "bottom";

  /**
   * 是否展示分割线
   * @default false
   */
  showSplitLine?: boolean;

  /**
   * 包括的栅格列，请使用 <Col /> 作为子节点
   */
  children?: ColChild | ColChild[];
}

export interface ColProps extends StyledProps {
  /**
   * 栅格占位格数
   *
   * *为 0 时不显示当前 Col*
   */
  span?: number;

  /**
   * `< 540px` 响应式格栅
   * @since 2.7.0
   */
  xs?: number;

  /**
   * `≥ 540px` 响应式格栅
   * @since 2.7.0
   */
  sm?: number;

  /**
   * `≥ 768px` 响应式格栅
   * @since 2.7.0
   */
  md?: number;

  /**
   * `≥ 900px` 响应式格栅
   * @since 2.7.0
   */
  lg?: number;

  /**
   * `≥ 1220px` 响应式格栅
   * @since 2.7.0
   */
  xl?: number;

  /**
   * `≥ 1400px` 响应式格栅
   * @since 2.7.0
   */
  xxl?: number;

  /**
   * 栅格单元中内容
   */
  children?: React.ReactNode;
}

interface GridContextValue {
  gap: number;
}

const GridContext = React.createContext<GridContextValue>({ gap: 20 });

export const Row = forwardRef(function Row(
  {
    gap,
    verticalAlign,
    showSplitLine,
    children,
    className,
    style,
    ...props
  }: RowProps,
  ref: React.Ref<HTMLDivElement>
) {
  const { classPrefix } = useConfig();
  let grid: GridContextValue = null;
  let rowStyle: React.CSSProperties = null;

  // 定义了 gap 的，才生成一个 grid 上下文，否则使用默认样式即可
  if (typeof gap === "number") {
    grid = { gap };
    rowStyle = {
      marginLeft: -gap / 2,
      marginRight: -gap / 2,
    };
  }

  rowStyle = {
    ...(rowStyle || {}),
    ...(style || {}),
  };

  const rowClassName = classNames(
    `${classPrefix}-row`,
    `${classPrefix}-grid`,
    className,
    {
      [`${classPrefix}-grid--split-line`]: showSplitLine,
      [`${classPrefix}-vertical--${verticalAlign}`]: verticalAlign,
    }
  );

  return (
    <div className={rowClassName} style={rowStyle} {...props} ref={ref}>
      <GridContext.Provider value={grid}>{children}</GridContext.Provider>
    </div>
  );
});

Row.displayName = "Row";

export const Col = forwardRef(function Col(
  {
    xs,
    sm,
    md,
    lg,
    xl,
    xxl,
    span = xs,
    className,
    style,
    children,
    ...props
  }: ColProps,
  ref: React.Ref<HTMLDivElement>
) {
  const { classPrefix } = useConfig();
  const grid = useContext(GridContext);

  let colStyle: React.CSSProperties = null;
  if (grid) {
    colStyle = {
      paddingLeft: grid.gap / 2,
      paddingRight: grid.gap / 2,
    };
  }

  const colClassName = classNames(
    `${classPrefix}-col`,
    `${classPrefix}-grid__item${span != null ? `-${span}` : ""}`,
    {
      [`${classPrefix}-grid__item-xs-${xs}`]: xs != null,
      [`${classPrefix}-grid__item-sm-${sm}`]: sm != null,
      [`${classPrefix}-grid__item-md-${md}`]: md != null,
      [`${classPrefix}-grid__item-lg-${lg}`]: lg != null,
      [`${classPrefix}-grid__item-xl-${xl}`]: xl != null,
      [`${classPrefix}-grid__item-xxl-${xxl}`]: xxl != null,
    },
    className
  );

  colStyle = {
    ...(colStyle || {}),
    ...(style || {}),
  };

  // 有改变内层属性需求，文档不暴露该属性
  const { innerProps = {}, ...restProps } = props as any;

  return (
    <div className={colClassName} style={colStyle} {...restProps} ref={ref}>
      <div
        {...innerProps}
        className={classNames(
          `${classPrefix}-grid__box`,
          innerProps?.className
        )}
      >
        {children}
      </div>
    </div>
  );
});

Col.displayName = "Col";

type ColChild = React.ReactElement<ColProps, typeof Col>;
