"use strict";

exports.__esModule = true;
exports.default = CommentsFeedObject;

var _react = _interopRequireWildcard(require("react"));

var _styles = require("@mui/material/styles");

var _reactIntl = require("react-intl");

var _CommentObject = _interopRequireDefault(require("../CommentObject"));

var _material = require("@mui/material");

var _comments = require("../../types/comments");

var _classnames = _interopRequireDefault(require("classnames"));

var _useThemeProps = _interopRequireDefault(require("@mui/material/styles/useThemeProps"));

var _CommentsObject = _interopRequireDefault(require("../CommentsObject"));

var _Errors = require("../../constants/Errors");

var _Typography = _interopRequireDefault(require("@mui/material/Typography"));

var _contribution = require("../../utils/contribution");

var _core = require("@selfcommunity/core");

const _excluded = ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "commentObjectId", "commentObject", "CommentComponent", "CommentComponentProps", "CommentObjectSkeletonProps", "renderNoComments", "renderCommentNotFound", "page", "commentsPageCount", "commentsOrderBy", "showTitle", "infiniteScrolling", "onChangePage", "comments"];

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

const PREFIX = 'SCCommentsFeedObject';
const classes = {
  root: `${PREFIX}-root`,
  noComments: `${PREFIX}-no-comments`,
  commentNotFound: `${PREFIX}-comment-not-found`
};
const Root = (0, _styles.styled)(_material.Box, {
  name: PREFIX,
  slot: 'Root',
  overridesResolver: (props, styles) => styles.root
})(({
  theme
}) => ({
  width: '100%',
  [`& .${classes.noComments}`]: {
    padding: theme.spacing()
  },
  [`& .${classes.commentNotFound}`]: {
    padding: theme.spacing()
  }
}));

/**
 *> API documentation for the Community-UI Comments Object component. Learn about the available props and the CSS API.

 #### Import

 ```jsx
 import {CommentsObject} from '@selfcommunity/ui';
 ```

 #### Component Name

 The name `SCCommentsObject` can be used when providing style overrides in the theme.

 #### CSS

 |Rule Name|Global class|Description|
 |---|---|---|
 |root|.SCCommentsObject-root|Styles applied to the root element.|
 |commentNotFound|.SCCommentsObject-comment-not-found|Styles applied to the label 'Comment not found'.|
 |noComments|.SCCommentsObject-no-comments|Styles applied to the 'no comments' section.|

 * @param inProps
 */
function CommentsFeedObject(inProps) {
  const props = (0, _useThemeProps.default)({
    props: inProps,
    name: PREFIX
  }); // PROPS

  const {
    id = `comments_object_${props.feedObjectType ? props.feedObjectType : props.feedObject ? props.feedObject.type : ''}_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`,
    className,
    feedObjectId,
    feedObject,
    feedObjectType = _core.SCFeedObjectTypologyType.POST,
    commentObjectId,
    commentObject,
    CommentComponent = _CommentObject.default,
    CommentComponentProps = {
      variant: 'outlined'
    },
    CommentObjectSkeletonProps = {
      elevation: 0,
      WidgetProps: {
        variant: 'outlined'
      }
    },
    renderNoComments,
    renderCommentNotFound,
    page = 1,
    commentsPageCount = 5,
    commentsOrderBy = _comments.SCCommentsOrderBy.ADDED_AT_ASC,
    showTitle = false,
    infiniteScrolling = true,
    onChangePage,
    comments = []
  } = props,
        rest = _objectWithoutPropertiesLoose(props, _excluded); // STATE


  const [isLoading, setIsLoading] = (0, _react.useState)(false);
  const [comment, setComment] = (0, _react.useState)(null);
  const {
    obj: commentObj,
    error: errorCommentObj
  } = (0, _core.useSCFetchCommentObject)({
    id: commentObjectId,
    commentObject
  });
  const [commentError, setCommentError] = (0, _react.useState)(null);
  const commentsObject = (0, _core.useSCFetchCommentObjects)({
    id: feedObjectId,
    feedObject,
    feedObjectType,
    offset: (page - 1) * commentsPageCount,
    pageSize: commentsPageCount,
    orderBy: commentsOrderBy,
    onChangePage: onChangePage
  }); // CONST

  const objId = commentsObject.feedObject ? commentsObject.feedObject.id : null;
  const commentObjId = commentObj ? commentObj.id : null;
  /**
   * Total number of comments
   */

  const total = commentsObject.total + comments.length;
  /**
   * Render title
   */

  const renderTitle = (0, _react.useMemo)(() => () => {
    if (showTitle) {
      return /*#__PURE__*/_react.default.createElement(_Typography.default, {
        variant: "h6",
        gutterBottom: true,
        color: 'inherit'
      }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
        id: "ui.commentsObject.title",
        defaultMessage: "ui.commentsObject.title",
        values: {
          total
        }
      }));
    }

    return null;
  }, [total]);
  /**
   * Render no comments
   */

  function renderNoCommentsFoundError() {
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderNoComments ? renderNoComments() : /*#__PURE__*/_react.default.createElement(_material.Box, {
      className: classes.noComments
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.noComments",
      defaultMessage: "ui.commentsObject.noComments"
    })));
  }
  /**
   * Render comment not found
   */


  function renderCommentNotFoundError() {
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderCommentNotFound ? renderCommentNotFound() : /*#__PURE__*/_react.default.createElement(_material.Box, {
      className: classes.commentNotFound
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.commentNotFound",
      defaultMessage: "ui.commentsObject.commentNotFound"
    })));
  }
  /**
   * Get a single comment
   */


  const performFetchComment = (0, _react.useMemo)(() => commentId => {
    return _core.http.request({
      url: _core.Endpoints.Comment.url({
        id: commentId
      }),
      method: _core.Endpoints.Comment.method
    }).then(res => {
      if (res.status >= 300) {
        return Promise.reject(res);
      }

      return Promise.resolve(res.data);
    });
  }, [commentsObject.feedObject, commentObjectId, commentObj]);
  /**
   * Fetch a single comment
   * and comment parent (if need it)
   */

  function fetchComment() {
    if (commentObj) {
      if (commentObj.parent) {
        setIsLoading(true);
        performFetchComment(commentObj.parent).then(parent => {
          const _parent = Object.assign({}, parent);

          _parent.latest_comments = [commentObj];

          if ((0, _contribution.getContribution)(parent).id === commentsObject.feedObject.id) {
            setComment(_parent);
          } else {
            setCommentError(true);
          }

          setIsLoading(false);
        }).catch(error => {
          // Comment not found
          setIsLoading(false);

          _core.Logger.error(_Errors.SCOPE_SC_UI, error);
        });
      } else {
        if ((0, _contribution.getContribution)(commentObj).id === commentsObject.feedObject.id) {
          setComment(commentObj);
        } else {
          setCommentError(true);
        }

        setIsLoading(false);
      }
    } else if (errorCommentObj) {
      setIsLoading(false);
    }
  }
  /**
   * Prefetch comments only if obj exists
   */


  (0, _react.useEffect)(() => {
    if (objId !== null && !isLoading) {
      if (commentObjectId || commentObj) {
        fetchComment();
      } else if (!isLoading) {
        commentsObject.getNextPage();
      }
    }
  }, [objId, commentObjId, errorCommentObj]);
  /**
   * Render comments
   */

  let commentsRendered = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null);

  if (commentsObject.componentLoaded && !total && !commentsObject.isLoadingNext && !isLoading) {
    /**
     * If comments were not found and loading is finished
     * and the component was not looking for a particular
     * comment render no comments message
     */
    commentsRendered = renderNoCommentsFoundError();
  } else {
    /**
     * Two modes available:
     *  - infinite scroll
     *  - load pagination with load more button
     *  !IMPORTANT:
     *  the component will switch to 'load more pagination' mode automatically
     *  in case it needs to display a single comment
     */
    commentsRendered = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (commentError || errorCommentObj) && !isLoading && !total && renderCommentNotFoundError(), /*#__PURE__*/_react.default.createElement(_CommentsObject.default, {
      feedObject: commentsObject.feedObject,
      comments: commentsObject.comments,
      endComments: [...(comment ? [comment] : []), ...(commentsOrderBy === _comments.SCCommentsOrderBy.ADDED_AT_ASC ? comments : [])],
      startComments: [...(commentsOrderBy === _comments.SCCommentsOrderBy.ADDED_AT_ASC ? [] : comments)],
      previous: commentsObject.previous,
      handlePrevious: commentsObject.getPreviousPage,
      isLoadingPrevious: commentsObject.isLoadingPrevious,
      next: commentsObject.next,
      isLoadingNext: commentsObject.isLoadingNext,
      handleNext: commentsObject.getNextPage,
      page: commentsObject.page,
      infiniteScrolling: infiniteScrolling && commentsObject.total > 0 && !comment && !comments.length,
      CommentComponentProps: CommentComponentProps,
      CommentComponent: CommentComponent,
      CommentObjectSkeletonProps: CommentObjectSkeletonProps
    }));
  }
  /**
   * Renders root object
   */


  return /*#__PURE__*/_react.default.createElement(Root, _extends({
    id: id,
    className: (0, _classnames.default)(classes.root, className)
  }, rest), renderTitle(), commentsRendered);
}