"use strict";

exports.__esModule = true;
exports.default = CommentsObject;

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

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

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

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

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

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

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

var _CustomAdv = _interopRequireDefault(require("../CustomAdv"));

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

var _Skeleton = _interopRequireDefault(require("./Skeleton"));

var _reactIntersectionObserver = require("react-intersection-observer");

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

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

var _url = require("../../utils/url");

const _excluded = ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "CommentComponent", "CommentComponentProps", "CommentObjectSkeletonProps", "CommentsObjectSkeletonProps", "next", "isLoadingNext", "handleNext", "previous", "isLoadingPrevious", "handlePrevious", "totalLoadedComments", "totalComments", "page", "comments", "startComments", "endComments", "infiniteScrolling", "hideAdvertising"];

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 = 'SCCommentsObject';
const classes = {
  root: `${PREFIX}-root`,
  loadNextCommentsButton: `${PREFIX}-load-more-comments-button`,
  loadPreviousCommentsButton: `${PREFIX}-load-previous-comments-button`,
  paginationLink: `${PREFIX}-pagination-link`,
  pagination: `${PREFIX}-pagination`,
  commentsCounter: `${PREFIX}-comments-counter`,
  commentNotFound: `${PREFIX}-comment-not-found`,
  noOtherComments: `${PREFIX}-no-other-comment`
};
const Root = (0, _styles.styled)(_material.Box, {
  name: PREFIX,
  slot: 'Root',
  overridesResolver: (props, styles) => styles.root
})(({
  theme
}) => ({
  boxShadow: 'none',
  position: 'relative',
  display: 'flex',
  flexWrap: 'wrap',
  width: '100%',
  [`& .${classes.loadNextCommentsButton}`]: {
    textTransform: 'initial'
  },
  [`& .${classes.loadPreviousCommentsButton}`]: {
    textTransform: 'initial'
  },
  [`& .${classes.commentsCounter}`]: {
    paddingRight: theme.spacing()
  },
  [`& .${classes.pagination}`]: {
    width: '100%'
  },
  [`& .${classes.paginationLink}`]: {
    display: 'none'
  }
}));
const PREFERENCES = [_core.SCPreferences.ADVERTISING_CUSTOM_ADV_ENABLED, _core.SCPreferences.ADVERTISING_CUSTOM_ADV_ONLY_FOR_ANONYMOUS_USERS_ENABLED];
/**
 *> 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.|
 |pagination|.SCCommentsObject-pagination|Styles applied to the pagination controls.|
 |paginationLink|.SCCommentsObject-pagination-link|Styles applied to the pagination link.|
 |loadNextCommentsButton|.SCCommentsObject-load-next-comments-button|Styles applied to the load next comments button.|
 |loadPreviousCommentsButton|.SCCommentsObject-load-previous-comments-button|Styles applied to the load previous comments button.|
 |commentsCounter|.SCCommentsObject-comments-counter|Styles applied to the comments counter element.|

 * @param inProps
 */

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

  const {
    id = `comments_object_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`,
    className,
    feedObjectId,
    feedObject,
    feedObjectType = _core.SCFeedObjectTypologyType.POST,
    CommentComponent = _CommentObject.default,
    CommentComponentProps = {
      variant: 'outlined'
    },
    CommentObjectSkeletonProps = {
      elevation: 0,
      WidgetProps: {
        variant: 'outlined'
      }
    },
    CommentsObjectSkeletonProps = {},
    next,
    isLoadingNext,
    handleNext,
    previous,
    isLoadingPrevious,
    handlePrevious,
    totalLoadedComments,
    totalComments,
    page,
    comments = [],
    startComments = [],
    endComments = [],
    infiniteScrolling = false,
    hideAdvertising = false
  } = props,
        rest = _objectWithoutPropertiesLoose(props, _excluded); // CONTEXT


  const scUserContext = (0, _core.useSCUser)();
  const scPreferences = (0, _core.useSCPreferences)();
  const scRoutingContext = (0, _core.useSCRouting)();
  const {
    obj
  } = (0, _core.useSCFetchFeedObject)({
    id: feedObjectId,
    feedObject,
    feedObjectType
  });
  const commentsIds = comments.map(c => c.id);
  /**
   * Compute preferences
   */

  const preferences = (0, _react.useMemo)(() => {
    const _preferences = {};
    PREFERENCES.map(p => _preferences[p] = p in scPreferences.preferences ? scPreferences.preferences[p].value : null);
    return _preferences;
  }, [scPreferences.preferences]);
  /**
   * Render advertising above FeedObject Detail
   */

  const renderAdvertising = (0, _react.useMemo)(() => () => {
    if (obj && !hideAdvertising && preferences[_core.SCPreferences.ADVERTISING_CUSTOM_ADV_ENABLED] && (preferences[_core.SCPreferences.ADVERTISING_CUSTOM_ADV_ONLY_FOR_ANONYMOUS_USERS_ENABLED] && scUserContext.user === null || !preferences[_core.SCPreferences.ADVERTISING_CUSTOM_ADV_ONLY_FOR_ANONYMOUS_USERS_ENABLED])) {
      return /*#__PURE__*/_react.default.createElement(_CustomAdv.default, _extends({
        position: _core.SCCustomAdvPosition.POSITION_IN_COMMENTS
      }, obj.categories.length && {
        categoriesId: obj.categories.map(c => c.id)
      }));
    }

    return null;
  }, [JSON.stringify(obj)]);
  /**
   * Handle open reply box
   * @param comment
   */

  function openReplyBox(comment) {
    setTimeout(() => {
      const element = document.getElementById(`reply-${comment.id}`);
      element && element.scrollIntoView({
        behavior: 'smooth',
        block: 'center'
      });
    }, 200);
  }
  /**
   * handle on scroll end
   * @param inView
   * @param entry
   */


  function handleScrollEnd(inView, entry) {
    if (infiniteScrolling && inView && !isLoadingNext) {
      handleNext && handleNext();
    }
  }
  /**
   * Check if show Comments counter
   */


  function showCommentsCounter() {
    return Boolean(totalComments && totalLoadedComments);
  }
  /**
   * Render button load previous comments
   */


  function renderLoadPreviousComments() {
    return /*#__PURE__*/_react.default.createElement(_material.Box, {
      className: classes.pagination
    }, isLoadingPrevious && /*#__PURE__*/_react.default.createElement(_CommentObject.CommentObjectSkeleton, _extends({}, CommentObjectSkeletonProps, {
      count: 1
    })), !isLoadingPrevious && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_material.Button, {
      variant: "text",
      onClick: handlePrevious,
      disabled: isLoadingPrevious,
      color: "inherit",
      classes: {
        root: classes.loadPreviousCommentsButton
      }
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.loadPreviousComments",
      defaultMessage: "ui.commentsObject.loadPreviousComments"
    })), page && /*#__PURE__*/_react.default.createElement(_core.Link, {
      to: `${(0, _url.appendURLSearchParams)(scRoutingContext.url((0, _contribution.getContributionRouteName)(feedObject), (0, _contribution.getRouteData)(feedObject)), [{
        page: page - 1
      }])}`,
      className: classes.paginationLink
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.previousComments",
      defaultMessage: "ui.commentsObject.previousComments"
    }))));
  }
  /**
   * Footer with n comments of, only for load more pagination mode
   */


  function renderLoadNextComments() {
    return /*#__PURE__*/_react.default.createElement(_material.Box, {
      className: classes.pagination
    }, !isLoadingNext && /*#__PURE__*/_react.default.createElement(_reactIntersectionObserver.InView, {
      as: "div",
      onChange: handleScrollEnd,
      threshold: 0.5
    }, /*#__PURE__*/_react.default.createElement(_material.Stack, {
      direction: "row",
      justifyContent: "space-between",
      alignItems: "center",
      spacing: 2
    }, /*#__PURE__*/_react.default.createElement(_material.Button, {
      variant: "text",
      onClick: handleNext,
      disabled: isLoadingNext,
      color: "inherit",
      classes: {
        root: classes.loadNextCommentsButton
      }
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.loadMoreComments",
      defaultMessage: "ui.commentsObject.loadMoreComments"
    })), page && /*#__PURE__*/_react.default.createElement(_core.Link, {
      to: `${(0, _url.appendURLSearchParams)(scRoutingContext.url((0, _contribution.getContributionRouteName)(feedObject), (0, _contribution.getRouteData)(feedObject)), [{
        page: page + 1
      }])}`,
      className: classes.paginationLink
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.nextComments",
      defaultMessage: "ui.commentsObject.nextComments"
    })), showCommentsCounter() && /*#__PURE__*/_react.default.createElement(_Typography.default, {
      variant: "body1",
      classes: {
        root: classes.commentsCounter
      }
    }, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
      id: "ui.commentsObject.numberOfComments",
      defaultMessage: "ui.commentsObject.numberOfComments",
      values: {
        loaded: totalLoadedComments,
        total: totalComments
      }
    })))), isLoadingNext && /*#__PURE__*/_react.default.createElement(_CommentObject.CommentObjectSkeleton, _extends({}, CommentObjectSkeletonProps, {
      count: 1
    })));
  }
  /**
   * Remove duplicate comments (from header or footer)
   * @param comments
   */


  function getFilteredComments(comments) {
    return comments.filter(c => !commentsIds.includes(c.id));
  }
  /**
   * Render comments and load others with load more button
   */


  function renderComments(comments) {
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, comments.map((comment, index) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, {
      key: index
    }, /*#__PURE__*/_react.default.createElement(CommentComponent, _extends({
      key: comment.id,
      commentObject: comment,
      onOpenReply: openReplyBox,
      feedObject: obj
    }, CommentComponentProps)), advPosition === index && renderAdvertising())));
  }
  /**
   * Render comments
   */


  const advPosition = Math.floor(Math.random() * (Math.min(totalComments, 5) - 1 + 1) + 1);

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

  if (!obj || (isLoadingPrevious || isLoadingNext) && !comments.length) {
    /**
     * Until the contribution has not been founded and there are
     * no comments during loading render skeletons
     */
    commentsRendered = /*#__PURE__*/_react.default.createElement(_Skeleton.default, _extends({}, CommentsObjectSkeletonProps, {
      CommentObjectSkeletonProps: CommentObjectSkeletonProps,
      elevation: 0
    }));
  } else {
    /**
     * Two modes available:
     *  - infinite scroll
     *  - load pagination with load next comment button
     *  !IMPORTANT:
     *  the component will switch to 'load more pagination' mode automatically
     *  in case it needs to display a single comment or newComments
     */
    commentsRendered = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, previous && renderLoadPreviousComments(), renderComments(comments), next && renderLoadNextComments());
  }
  /**
   * Renders root object
   */


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