import PropTypes from 'prop-types';
import { keys, omit } from 'ramda';
import React, { Component } from 'react';
import { Rating } from 'semantic-ui-react';

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

/* Interface */
const propTypes = {
  /** ID of post to load. */
  id: ItemPropTypes.id,

  /** The post if already available. */
  item: PropTypes.shape({
    id: PropTypes.number.isRequired,
    rating: PropTypes.shape({
      average: PropTypes.number,
      count: PropTypes.number.isRequired,
      own: PropTypes.number,
    }),
    type: PropTypes.string.isRequired,
  }).isRequired,

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

  /** The total number of icons. */
  maxRating: PropTypes.number.isRequired,

  /**
   * Called after user's click.
   * @param {SyntheticEvent} event - React's original SyntheticEvent.
   * @param {Object} data - All props and proposed rating.
   */
  onRate: PropTypes.func,

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

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

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

/**
 * Item rating
 * Additional props will be passed through to SUI's `<Rating>` component.
 * @returns {Object} component
 */
export class ItemRating extends Component {
  /**
   * Sends a rating to StoryShare
   * The response should contain a `self` link, so the DL will store the updated
   * item and we'll get re-rendered by the parent `<Item>`.
   * @param {SyntheticEvent} event - React's original SyntheticEvent.
   * @param {Object} data - All props and proposed rating.
   * @returns {void}
   */
  handleRate = (event, data) => {
    const { item: { id, type }, onRate, site } = this.props;
    const { maxRating, rating } = data;

    const request = site.req(`${type}/${id}/rating`);

    if (rating) {
      request
        .addParam('rating', rating / maxRating)
        .create();
    } else {
      request.delete();
    }

    if (onRate) {
      onRate(event, data);
    }
  };

  render = () => {
    const { item: { rating }, maxRating } = this.props;

    if (!rating) {
      return null;
    }

    return (
      <Rating
        maxRating={ maxRating }
        onRate={ this.handleRate }
        rating={ rating.own && rating.own * maxRating }
        { ...omit(keys(propTypes), this.props) }
      />
    );
  };
}

ItemRating.propTypes = propTypes;

// n.b. ordering: inject the `site` prop into the wrapped component
export default withSite(createItemComponent()(ItemRating));
