import { RecoilRoot } from 'recoil';
import PropTypes from 'prop-types';
import { BreakpointHydrator } from "../../../atoms/breakpoint/index.js";
import { TimeHydrator, now, startTime } from "../../../atoms/time/index.js";
import { TrackingHydrator } from "../../../atoms/tracking/index.js";

/**
 * A [Recoil data store provider][recoil-root] that can be used to manage
 * global state for your application. By default it initializes the
 * `breakpoint` atoms. If you pass configuration options for the `time` atoms
 * with the `time` prop it will configure those as well, but they are _not_
 * configured by default, meaning that intervals will all return `undefined`
 * out of the box.
 *
 * ```js
 *
 * import { AtomsRoot } from '@politico/interactive-style';
 * ```
 *
 * [recoil-root]: https://recoiljs.org/docs/api-reference/core/RecoilRoot
 */
const AtomsRoot = function AtomsRoot(props) {
  const {
    initializeState,
    time,
    tracking,
    children
  } = props;
  const {
    startTime: startTimeValue,
    now: nowValue
  } = time;
  const {
    pib,
    baseConfig,
    variants
  } = tracking;
  return <RecoilRoot initializeState={snapshot => {
    if (startTimeValue) {
      snapshot.set(now, new Date(nowValue || startTimeValue));
      snapshot.set(startTime, new Date(startTimeValue));
    }
    if (initializeState) {
      initializeState(snapshot);
    }
  }}>
      <BreakpointHydrator />
      <TimeHydrator now={time.now} updateInterval={time.updateInterval} />
      <TrackingHydrator pib={pib} baseConfig={baseConfig} variants={variants} />
      {children}
    </RecoilRoot>;
};
AtomsRoot.defaultProps = {
  time: {
    updateInterval: -1
  },
  tracking: {},
  initializeState: undefined
};
AtomsRoot.propTypes = {
  /**
   * Initialization function to initialize the Recoil state via
   * a `MutableSnapshot`. See [the Recoil documentation][docs] for more
   * information.
   *
   * [docs]: https://recoiljs.org/docs/api-reference/core/Snapshot/#state-initialization
   */
  initializeState: PropTypes.func,
  /**
   * Configuration options for initializing the `time` atoms. The `startTime`
   * option initializes a starting value for the `now` atom (useful for SSR),
   * and the `updateInterval` option configures how frequently the `now` atom
   * will be updated in milliseconds. Note that if `updateInterval` is less
   * than 0, the `now` atom will not update automatically.
   */
  time: PropTypes.shape({
    now: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Date)]),
    startTime: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.instanceOf(Date)]),
    updateInterval: PropTypes.number
  }),
  /**
   * Configuration options for tracking.
   */
  tracking: PropTypes.shape({
    pib: PropTypes.shape({}),
    baseConfig: PropTypes.shape({}),
    variants: PropTypes.shape({})
  }),
  /**
   * The children to render inside this Recoil root, for which the provided
   * data store will be available.
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]).isRequired
};
export default AtomsRoot;