import PropTypes from 'prop-types';
import { always, filter, isEmpty, isNil, keys, map, omit, path } from 'ramda';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Form, Loader } from 'semantic-ui-react';

import { withSite } from '../../addons/Site';
import { printWarning } from '../../lib/console';

/* Interface */
const propTypes = {
  /**
   * From react-redux `mapDispatchToProps`
   * @private
   */
  dispatch: PropTypes.func,

  /** Predicate to restrict which items show up. */
  filterPredicate: PropTypes.func,

  /**
   * Loaded posts or terms.
   * @private
   */
  items: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    name: PropTypes.string,
    title: PropTypes.shape({ rendered: PropTypes.string.isRequired }),
  }).isRequired),

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

  /** Additional parameters to include in the API request. */
  requestParams: PropTypes.object,

  /**
   * StoryShare `Site`.
   * @private
   */
  site: PropTypes.object.isRequired,

  /** Slug for post type or taxonomy from which posts or terms are drawn. */
  typeSlug: PropTypes.string.isRequired,

  /** The HTML input value. */
  value: PropTypes.number,
};

/* Defaults */
const defaultProps = {
  filterPredicate: always(true),
  placeholder: <Loader active inline />,
  requestParams: { },
};

/**
 * Parameters for use when requesting posts or terms
 */
const DEFAULT_PARAMS = { per_page: 100 };

/**
 * Assembles all request parameters into a single object
 * @param {Object} requestParams - Extra request parameters.
 * @returns {Object} assembled parameters
 */
const assembleParams = (requestParams) => ({
  ...DEFAULT_PARAMS,
  ...requestParams,
});

/**
 * Radio buttons for choosing "items" (either posts or taxonomy terms)
 * Supports up to 100 items.
 * The following props are required.
 * Additional props will be passed through to SUI's <Radio> components.
 * @returns {Object} component
 */
export class ItemRadios extends Component {
  /**
   * Loads posts or terms when the component mounts
   * Note that only the first 100 posts or terms will be displayed.
   * @returns {void}
   */
  componentDidMount = () => {
    const { typeSlug, requestParams, site } = this.props;
    site.req(typeSlug)
      .read(assembleParams(requestParams));

    printWarning(
      'storyshare-sui-react-components:'
        + ' The <ItemRadios> component is deprecated.'
        + ' Please update your code to use <Collection.Radios> instead.'
    );
  };

  render = () => {
    const { filterPredicate, items, placeholder, value } = this.props;

    if (isNil(items) || isEmpty(items)) {
      return placeholder;
    }

    return (
      <>
        { map((item) => (
          <Form.Radio
            checked={ item.id === value }
            key={ item.id }
            label={ path(['title', 'rendered'], item) || item.name }
            value={ item.id }
            { ...omit(keys(propTypes), this.props) }
          />
        ), filter(filterPredicate, items)) }
      </>
    );
  };
}

ItemRadios.propTypes = propTypes;
ItemRadios.defaultProps = defaultProps;

export const mapStateToProps = (_, { requestParams, site, typeSlug }) => ({
  items: site.getCollectionByRoute(typeSlug, assembleParams(requestParams)),
});

// n.b. ordering: mapStateToProps needs site
export default withSite(connect(mapStateToProps)(ItemRadios));
