import PropTypes from 'prop-types';
import { path } from 'ramda';
import React from 'react';

import createItemComponent, {
  propTypes as ItemPropTypes,
} from './createItemComponent';

/* Interface */
const propTypes = {
  /** An element type to render as (string or function). */
  as: PropTypes.oneOfType([
    PropTypes.func.isRequired,
    PropTypes.string.isRequired,
  ]),

  /** Function to call with loaded value. */
  children: PropTypes.func,

  /** Field to retrieve (can be a dot-separated path). */
  field: PropTypes.string.isRequired,

  /** ID of post or term to load. */
  id: ItemPropTypes.id,

  /**
   * Loaded post or term
   * @private
   */
  item: PropTypes.object.isRequired,

  /** Slug of post or term to load. */
  itemSlug: ItemPropTypes.itemSlug,

  /** Content to display while awaiting data. */
  placeholder: ItemPropTypes.placeholder,

  /** Slug for post type or taxonomy from which posts or terms are drawn. */
  typeSlug: ItemPropTypes.typeSlug,
};

/**
 * Item field
 * Retrieves a custom field value from the item and renders it in place.
 * Alternatively pass a functional child which will be passed the loaded value
 * when it becomes available, or specify a component to render using `as`.
 * Additional props will be passed through to any component specified by the
 * `as` prop.
 * @param {Object} props - React component props.
 * @returns {Object} React element.
 */
export const ItemField = ({
  as: Component,
  children,
  field,
  item,
  ...passThroughProps
}) => {
  const value = path(field.split('.'), item);
  if (typeof value === 'undefined') {
    return null;
  }

  if (Component) {
    return <Component { ...passThroughProps }>{ value }</Component>;
  } else if (children) {
    return children(value);
  } else {
    return value;
  }
};

ItemField.propTypes = propTypes;

export default createItemComponent()(ItemField);
