"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const styles_1 = require("@mui/material/styles");
const react_intl_1 = require("react-intl");
const CommentObject_1 = tslib_1.__importDefault(require("../CommentObject"));
const material_1 = require("@mui/material");
const comments_1 = require("../../types/comments");
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const system_1 = require("@mui/system");
const CommentsObject_1 = tslib_1.__importDefault(require("../CommentsObject"));
const Errors_1 = require("../../constants/Errors");
const Typography_1 = tslib_1.__importDefault(require("@mui/material/Typography"));
const contribution_1 = require("../../utils/contribution");
const api_services_1 = require("@selfcommunity/api-services");
const utils_1 = require("@selfcommunity/utils");
const react_core_1 = require("@selfcommunity/react-core");
const types_1 = require("@selfcommunity/types");
const Pagination_1 = require("../../constants/Pagination");
const constants_1 = require("./constants");
const classes = {
    root: `${constants_1.PREFIX}-root`,
    noComments: `${constants_1.PREFIX}-no-comments`,
    commentNotFound: `${constants_1.PREFIX}-comment-not-found`
};
const Root = (0, styles_1.styled)(material_1.Box, {
    name: constants_1.PREFIX,
    slot: 'Root'
})(() => ({}));
/**
 * > API documentation for the Community-JS Comments Feed Object component. Learn about the available props and the CSS API.
 *
 *
 * This component renders a list of comment items.
 * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/CommentsFeedObject)

 #### Import

 ```jsx
 import {CommentsFeedObject} from '@selfcommunity/react-ui';
 ```

 #### Component Name

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

 #### CSS

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

 * @param inProps
 */
function CommentsFeedObject(inProps) {
    const props = (0, system_1.useThemeProps)({
        props: inProps,
        name: constants_1.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 = types_1.SCContributionType.POST, commentObjectId, commentObject, CommentComponent = CommentObject_1.default, CommentComponentProps = { variant: 'outlined', linkableCommentDateTime: false }, CommentObjectSkeletonProps = { elevation: 0, WidgetProps: { variant: 'outlined' } }, renderNoComments, renderCommentNotFound, page = 1, commentsPageCount = Pagination_1.DEFAULT_PAGINATION_LIMIT, commentsOrderBy = comments_1.SCCommentsOrderBy.ADDED_AT_ASC, showTitle = false, infiniteScrolling = true, onChangePage, comments = [], cacheStrategy = utils_1.CacheStrategies.NETWORK_ONLY } = props, rest = tslib_1.__rest(props, ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "commentObjectId", "commentObject", "CommentComponent", "CommentComponentProps", "CommentObjectSkeletonProps", "renderNoComments", "renderCommentNotFound", "page", "commentsPageCount", "commentsOrderBy", "showTitle", "infiniteScrolling", "onChangePage", "comments", "cacheStrategy"]);
    // STATE
    const commentsObject = (0, react_core_1.useSCFetchCommentObjects)({
        id: feedObjectId,
        feedObject,
        feedObjectType,
        offset: (page - 1) * commentsPageCount,
        pageSize: commentsPageCount,
        orderBy: commentsOrderBy,
        onChangePage: onChangePage,
        cacheStrategy
    });
    const [isLoading, setIsLoading] = (0, react_1.useState)(false);
    const [comment, setComment] = (0, react_1.useState)(null);
    const { obj: commentObj, error: errorCommentObj } = (0, react_core_1.useSCFetchCommentObject)({ id: commentObjectId, commentObject, cacheStrategy });
    const [commentError, setCommentError] = (0, react_1.useState)(null);
    // CONST
    const objId = commentsObject.feedObject ? commentsObject.feedObject.id : null;
    const commentObjId = commentObj ? commentObj.id : null;
    // REFS
    const commentsContainerRef = (0, react_1.useRef)();
    /**
     * Total number of comments
     */
    const total = commentsObject.total + comments.length;
    /**
     * Render title
     */
    const renderTitle = (0, react_1.useMemo)(() => () => {
        if (showTitle) {
            return ((0, jsx_runtime_1.jsx)(Typography_1.default, Object.assign({ variant: "h6", gutterBottom: true, color: 'inherit' }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentsObject.title", defaultMessage: "ui.commentsObject.title", values: { total: total } }) })));
        }
        return null;
    }, [total, isLoading]);
    /**
     * Render no comments
     */
    function renderNoCommentsFound() {
        return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: renderNoComments ? (renderNoComments()) : ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.noComments }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentsObject.noComments", defaultMessage: "ui.commentsObject.noComments" }) }))) }));
    }
    /**
     * Render comment not found
     */
    function renderCommentNotFoundError() {
        return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: renderCommentNotFound ? (renderCommentNotFound()) : ((0, jsx_runtime_1.jsx)(material_1.Box, Object.assign({ className: classes.commentNotFound }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.commentsObject.commentNotFound", defaultMessage: "ui.commentsObject.commentNotFound" }) }))) }));
    }
    /**
     * Get a single comment
     */
    const performFetchComment = (0, react_1.useMemo)(() => (commentId) => {
        return api_services_1.http
            .request({
            url: api_services_1.Endpoints.Comment.url({ id: commentId }),
            method: api_services_1.Endpoints.Comment.method
        })
            .then((res) => {
            if (res.status >= 300) {
                return Promise.reject(res);
            }
            return Promise.resolve(res.data);
        });
    }, [commentsObject.feedObject, commentObjectId, commentObj]);
    /**
     * Focus on comment
     * @param comment
     */
    function scrollToComment(comment) {
        // Add (window.innerHeight / 2) to scroll
        // (usually >= (topBar + offset) and in center of the screen)
        setTimeout(() => {
            // Get the comment inside commentsContainer
            const el = commentsContainerRef.current ? commentsContainerRef.current.querySelector(`#comment_object_${comment.id}`) : null;
            if (el) {
                el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' });
            }
        }, 300);
    }
    /**
     * 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_1.getContribution)(parent).id === commentsObject.feedObject.id) {
                        setComment(_parent);
                        scrollToComment(commentObj);
                    }
                    else {
                        setCommentError(true);
                    }
                    setIsLoading(false);
                })
                    .catch((error) => {
                    // Comment not found
                    setIsLoading(false);
                    utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
                });
            }
            else {
                if ((0, contribution_1.getContribution)(commentObj).id === commentsObject.feedObject.id) {
                    setComment(commentObj);
                    scrollToComment(commentObj);
                }
                else {
                    setCommentError(true);
                }
                setIsLoading(false);
            }
        }
        else if (errorCommentObj) {
            setIsLoading(false);
        }
    }
    /**
     * Prefetch comments only if obj exists
     */
    (0, react_1.useEffect)(() => {
        if (objId !== null && !isLoading) {
            if (commentObjectId || commentObj) {
                fetchComment();
            }
            else if (!isLoading) {
                commentsObject.getNextPage();
            }
        }
    }, [objId, commentObjId]);
    /**
     * Render comments
     */
    let commentsRendered = (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
    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 = renderNoCommentsFound();
    }
    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 = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [Boolean((commentError || errorCommentObj) && !isLoading && !total) && renderCommentNotFoundError(), (0, jsx_runtime_1.jsx)(CommentsObject_1.default, { feedObject: commentsObject.feedObject, comments: commentsObject.comments, endComments: [...(comment ? [comment] : []), ...(commentsOrderBy === comments_1.SCCommentsOrderBy.ADDED_AT_ASC ? comments : [])], startComments: [...(commentsOrderBy === comments_1.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, previousPage: commentsObject.previousPage, nextPage: commentsObject.nextPage, infiniteScrolling: infiniteScrolling && commentsObject.total > 0 && !comment && !comments.length, CommentComponent: CommentComponent, CommentComponentProps: CommentComponentProps, CommentObjectSkeletonProps: CommentObjectSkeletonProps })] }));
    }
    /**
     * Renders root object
     */
    return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ id: id, className: (0, classnames_1.default)(classes.root, className) }, rest, { ref: commentsContainerRef }, { children: [renderTitle(), commentsRendered] })));
}
exports.default = CommentsFeedObject;
