import { Children, cloneElement, isValidElement, useEffect, useRef, useState } from "preact/compat";
import Alert from "../Alert/Alert";
import TableCaption from "./TableCaption";
import TableContext from "./TableContext";
import classNames from 'classnames';
import debounce from "../utilities/debounce";
import useId from "../utilities/useId";

/**
 * Determine if a ReactNode is a TableCaption
 */
import { jsx as _jsx } from "preact/compat/jsx-runtime";
function isTableCaption(child) {
  if (!child || !isValidElement(child)) {
    return false;
  }

  // Check child.type first and as a fallback, check child.type.displayName follow by child.type.name
  const componentName = child.type?.displayName || child.type?.name;
  return child.type === TableCaption || componentName === 'TableCaption';
}
/**
 * `Table` is a container component that contains `TableCaption`, `TableHead`
 * and `TableBody` as children, as well as `TableRow` and `TableCell` for the
 * table content. These components mostly follow ordinary HTML table semantics,
 * but also include some additional responsive features including horizontal
 * scrolling and vertically stacked rows.
 *
 * For information about how and when to use this component,
 * [refer to its full documentation page](https://design.cms.gov/components/table/).
 */
export const Table = _ref => {
  let {
    borderless,
    className,
    compact,
    stackable,
    stackableBreakpoint,
    striped,
    scrollable,
    scrollableNotice,
    warningDisabled,
    children,
    id,
    ...tableProps
  } = _ref;
  const [scrollActive, setScrollActive] = useState(false);
  const captionId = useId('table-caption--', id);
  if (process.env.NODE_ENV !== 'production') {
    if (scrollable && Array.isArray(children) && !children.some(child => isTableCaption(child))) {
      console.warn('The children prop in `Table` must include `TableCaption` component for scrollable tables.');
    }
  }
  const containerRef = useRef();
  useEffect(() => {
    if (!window || !scrollable) {
      return;
    }
    const handleResize = () => {
      if (containerRef.current) {
        const {
          scrollWidth,
          clientWidth
        } = containerRef.current;
        setScrollActive(scrollWidth > clientWidth);
      }
    };
    handleResize();
    const debounceHandleResize = debounce(handleResize, 500);
    window.addEventListener('resize', debounceHandleResize);
    return () => {
      window.removeEventListener('resize', debounceHandleResize);
    };
  }, [setScrollActive, scrollable]);
  const classes = classNames('ds-c-table', borderless ? 'ds-c-table--borderless' : null, compact ? 'ds-c-table--compact' : null, striped ? 'ds-c-table--striped' : null, stackable ? `ds-c-${stackableBreakpoint}-table--stacked` : null, className);

  /**
   * Makes table container focusable and displays the scrollable notice when table width exceeds viewport
   * by setting `tabIndex = 0` attribute.
   * This provides context for screen readers to the table's <caption> via aria-labelleby
   */
  const attributeScrollable = scrollable && {
    className: 'ds-c-table__wrapper',
    role: 'region',
    'aria-labelledby': captionId,
    tabIndex: scrollActive ? 0 : null
  };
  const contextValue = {
    stackable: !!stackable,
    warningDisabled: !!warningDisabled
  };
  const renderedChildren = Children.map(children, child => {
    if (isTableCaption(child)) {
      // Extend props on TableCaption before rendering.
      if (scrollable) {
        return cloneElement(child, {
          _id: captionId,
          _scrollActive: scrollActive,
          _scrollableNotice: scrollableNotice
        });
      }
    }
    return child;
  });
  const table = /*#__PURE__*/_jsx(TableContext.Provider, {
    value: contextValue,
    children: /*#__PURE__*/_jsx("table", {
      className: classes,
      ...tableProps,
      children: renderedChildren
    })
  });
  return scrollable ? /*#__PURE__*/_jsx("div", {
    ref: containerRef,
    "aria-live": "polite",
    "aria-relevant": "additions",
    ...attributeScrollable,
    children: table
  }) : table;
};
Table.defaultProps = {
  scrollableNotice: /*#__PURE__*/_jsx(Alert, {
    className: "ds-c-table__scroll-alert",
    role: "status",
    children: /*#__PURE__*/_jsx("p", {
      className: "ds-c-alert__text",
      children: "Scroll using arrow keys to see more"
    })
  }),
  stackableBreakpoint: 'sm'
};
export default Table;