import { forwardRef, useState, useCallback, useMemo } from 'react';
import { useSetRecoilState } from 'recoil';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import get from 'lodash/get';
import { pageUpdateTime } from "../../../atoms/election/index.js";
import ErrorBoundary from "../../application/ErrorBoundary/index.js";
import { useCurrentPage } from "../../../hooks/election/index.js";
import ModuleContext from './context';
import classes from './styles.module.scss';

/**
 * A container for an election module that exists within a layout. This
 * component accepts a forwarded ref and a custom `className` prop, so it can
 * be used as the `as` prop of a `ContainerBreakpoint` component.
 */
const ModuleContainer = forwardRef((props, ref) => {
  const {
    className,
    card,
    children,
    node,
    ...restProps
  } = props;
  const currentPage = useCurrentPage();
  const pageId = get(currentPage, 'metadata.id', undefined);
  const setPageUpdatedTime = useSetRecoilState(pageUpdateTime(pageId));
  const [lastUpdated, setLastUpdated] = useState();
  const registerTimestamp = useCallback(timestamp => {
    const updateOldTimestamp = old => {
      if (!old) return timestamp;
      if (timestamp && timestamp > old) return timestamp;
      return old;
    };
    setLastUpdated(updateOldTimestamp);
    setPageUpdatedTime(updateOldTimestamp);
  }, [setPageUpdatedTime]);
  const value = useMemo(() => ({
    lastUpdated,
    registerTimestamp
  }), [lastUpdated, registerTimestamp]);
  return <ErrorBoundary tracking={{
    context: node.type,
    detail: node.id
  }}>
      <ModuleContext.Provider value={value}>
        <div ref={ref} className={classnames(className, classes.container, {
        [classes.card]: card
      })} {...restProps} data-nodeid={node.id} data-nodetype={node.type}>
          {children}
        </div>
      </ModuleContext.Provider>
    </ErrorBoundary>;
});
ModuleContainer.displayName = 'ModuleContainer';
ModuleContainer.defaultProps = {
  className: undefined,
  card: true,
  node: {},
  children: undefined
};
ModuleContainer.propTypes = {
  /**
   * A custom CSS class to apply to the container. Mainly used to support using
   * this component as a `ContainerBreakpoint` wrapper.
   */
  className: PropTypes.string,
  /**
   * Wether to render this container as a card.
   */
  card: PropTypes.bool,
  /**
   * The Flatpack node
   */
  node: PropTypes.shape({
    id: PropTypes.string,
    type: PropTypes.string
  }),
  /**
   * The contents of the module.
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
};
export default ModuleContainer;