"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCollaboration = void 0;
var react_1 = require("react");
var ramda_1 = require("ramda");
var mdm_sdk_1 = require("@reltio/mdm-sdk");
var MdmModuleContext_1 = require("../../contexts/MdmModuleContext");
var filterReplies = function (replyId, replies) { return replies.filter(function (reply) { return reply.replyId !== replyId; }); };
var getUpdatedReplies = function (comment, reply) {
    var changedReplyIndex = comment.replies.findIndex(function (_a) {
        var replyId = _a.replyId;
        return replyId === reply.replyId;
    });
    var newReplies = __spreadArray([], comment.replies, true);
    newReplies[changedReplyIndex] = reply;
    return newReplies;
};
var defaultObjectIds = [];
var catchErrorInRequest = function (e) { return console.warn('Collaboration error', e); };
var useCollaboration = function (_a) {
    var _b = _a.objectIds, objectIds = _b === void 0 ? defaultObjectIds : _b, objectTypes = _a.objectTypes, _c = _a.enabled, enabled = _c === void 0 ? true : _c, _d = _a.needsTotalCount, needsTotalCount = _d === void 0 ? false : _d;
    var entity = (0, MdmModuleContext_1.useMdmEntity)();
    var tenant = (0, MdmModuleContext_1.useMdmTenant)();
    var collaborationPath = (0, MdmModuleContext_1.useMdmCollaborationPath)();
    var isCollaborationEnabled = (0, MdmModuleContext_1.useMdmIsCollaborationEnabled)() && enabled;
    var _e = (0, react_1.useState)(null), pageToken = _e[0], setPageToken = _e[1];
    var _f = (0, react_1.useState)([]), comments = _f[0], setComments = _f[1];
    var _g = (0, react_1.useState)(null), commentsMap = _g[0], setCommentsMap = _g[1];
    var _h = (0, react_1.useState)(null), totalCommentsCount = _h[0], setTotalCommentsCount = _h[1];
    var _j = (0, react_1.useState)(null), currentComment = _j[0], setCurrentComment = _j[1];
    var _k = (0, react_1.useState)(false), sending = _k[0], setSending = _k[1];
    var _l = (0, react_1.useState)(false), loading = _l[0], setLoading = _l[1];
    var _m = (0, react_1.useState)({}), collaborationStateMap = _m[0], setCollaborationStateMap = _m[1];
    var addCommentsToCommentsMap = (0, react_1.useCallback)(function (commentsMap) {
        setCommentsMap(function (currentCommentsMap) { return (__assign(__assign({}, currentCommentsMap), commentsMap)); });
    }, []);
    var entityUri = entity === null || entity === void 0 ? void 0 : entity.uri;
    var isCollaborationEnabledForEntity = isCollaborationEnabled && entityUri && !(0, mdm_sdk_1.isTempUri)(entityUri);
    var getCommentsCount = (0, react_1.useCallback)(function (objectIds, shouldResetCommentsMap) {
        if (shouldResetCommentsMap === void 0) { shouldResetCommentsMap = false; }
        if (!isCollaborationEnabledForEntity) {
            setCommentsMap(null);
            return;
        }
        var onError = function (e) {
            console.warn('Collaboration error', e);
            setCommentsMap(null);
        };
        (0, ramda_1.pipe)(mdm_sdk_1.getCommentsCount, (0, ramda_1.andThen)((0, ramda_1.map)((0, ramda_1.props)(['objectId', 'comments']))), (0, ramda_1.andThen)(ramda_1.fromPairs), (0, ramda_1.andThen)(shouldResetCommentsMap ? setCommentsMap : addCommentsToCommentsMap), (0, ramda_1.otherwise)(onError))({ uris: objectIds, tenant: tenant, collaborationPath: collaborationPath });
    }, [addCommentsToCommentsMap, collaborationPath, isCollaborationEnabledForEntity, tenant]);
    var getTotalCommentsCount = (0, react_1.useCallback)(function () {
        if (isCollaborationEnabledForEntity) {
            var onError = function (e) {
                console.warn('Collaboration error', e);
                setTotalCommentsCount(null);
            };
            (0, ramda_1.pipe)(mdm_sdk_1.getTotalCommentsCount, (0, ramda_1.andThen)((0, ramda_1.prop)('total')), (0, ramda_1.andThen)(setTotalCommentsCount), (0, ramda_1.otherwise)(onError))({
                relatedObjectUri: entityUri,
                collaborationPath: collaborationPath,
                tenant: tenant
            });
        }
        else {
            setTotalCommentsCount(null);
        }
    }, [isCollaborationEnabledForEntity, collaborationPath, entityUri, tenant]);
    (0, react_1.useEffect)(function () {
        if (needsTotalCount) {
            getTotalCommentsCount();
        }
    }, [getTotalCommentsCount, needsTotalCount]);
    (0, react_1.useEffect)(function () {
        getCommentsCount(objectIds, true);
    }, [objectIds, getCommentsCount]);
    var getComments = (0, react_1.useCallback)(function (relatedObjectUri, pageToken) {
        (0, mdm_sdk_1.getComments)({ collaborationPath: collaborationPath, tenant: tenant, relatedObjectUri: relatedObjectUri, pageToken: pageToken })
            .then(function (_a) {
            var items = _a.items, nextPageToken = _a.nextPageToken;
            setComments(function (prevComments) {
                if (!pageToken) {
                    return items;
                }
                return (0, ramda_1.uniqBy)((0, ramda_1.prop)('commentId'), __spreadArray(__spreadArray([], prevComments, true), items, true));
            });
            setPageToken(nextPageToken);
        })
            .catch(catchErrorInRequest);
    }, [collaborationPath, tenant]);
    var getComment = (0, react_1.useCallback)(function (commentId) {
        setLoading(true);
        (0, mdm_sdk_1.getComment)({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId })
            .then(setCurrentComment)
            .catch(catchErrorInRequest)
            .finally(function () { return setLoading(false); });
    }, [collaborationPath, tenant]);
    var addCommentToState = function (comment, uri) {
        setCurrentComment(comment);
        setCommentsMap(function (prevCommentsMap) {
            var _a;
            return __assign(__assign({}, prevCommentsMap), (_a = {}, _a[uri] = __spreadArray(__spreadArray([], (prevCommentsMap[uri] || []), true), [{ commentId: comment.commentId, replies: 0, status: 'open' }], false), _a));
        });
        setComments(function (prevComments) { return __spreadArray([comment], prevComments, true); });
        setTotalCommentsCount(function (prevCount) { return (prevCount || 0) + 1; });
    };
    var updateCommentInState = function (comment) {
        setCurrentComment(comment);
        setComments((0, ramda_1.map)((0, ramda_1.when)((0, ramda_1.propEq)('commentId', comment.commentId), (0, ramda_1.always)(comment))));
    };
    var deleteCommentFromState = function (commentId, uri) {
        var repliesCountFromComments;
        var repliesCountFromCommentsMap;
        setCurrentComment(null);
        setCommentsMap(function (prevCommentsMap) {
            var _a;
            var _b, _c;
            repliesCountFromCommentsMap = (_c = (_b = prevCommentsMap === null || prevCommentsMap === void 0 ? void 0 : prevCommentsMap[uri]) === null || _b === void 0 ? void 0 : _b.find(function (c) { return c.commentId === commentId; })) === null || _c === void 0 ? void 0 : _c.replies;
            var comments = prevCommentsMap[uri] || [];
            return __assign(__assign({}, prevCommentsMap), (_a = {}, _a[uri] = comments.filter(function (c) { return c.commentId !== commentId; }), _a));
        });
        setComments(function (prevComments) {
            var _a;
            repliesCountFromComments = (_a = prevComments.find(function (comment) { return comment.commentId === commentId; })) === null || _a === void 0 ? void 0 : _a.replies.length;
            return prevComments.filter(function (comment) { return comment.commentId !== commentId; });
        });
        setTotalCommentsCount(function (prevCount) { var _a; return Math.max((prevCount || 0) - (1 + ((_a = repliesCountFromComments !== null && repliesCountFromComments !== void 0 ? repliesCountFromComments : repliesCountFromCommentsMap) !== null && _a !== void 0 ? _a : 0)), 0); });
    };
    var createComment = (0, react_1.useCallback)(function (_a) {
        var content = _a.content, namedUsers = _a.namedUsers, objectType = _a.objectType, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris;
        setSending(true);
        var data = {
            objectId: uri,
            content: content,
            relatedObjectUris: relatedObjectUris,
            objectType: objectType,
            visibility: 'public',
            namedUsers: namedUsers,
            permanentLink: "".concat(window.location.href, "&commentId=").concat(encodeURIComponent('{commentId}'))
        };
        return (0, mdm_sdk_1.createComment)({ collaborationPath: collaborationPath, tenant: tenant, data: data })
            .then(function (_a) {
            var comment = _a[0];
            return addCommentToState(comment, uri);
        })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, tenant]);
    var editComment = (0, react_1.useCallback)(function (_a) {
        var content = _a.content, namedUsers = _a.namedUsers, objectType = _a.objectType, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, commentId = _a.commentId, replies = _a.replies;
        setSending(true);
        var data = {
            objectId: uri,
            content: content,
            relatedObjectUris: relatedObjectUris,
            objectType: objectType,
            visibility: 'public',
            namedUsers: namedUsers,
            commentId: commentId,
            replies: replies
        };
        return (0, mdm_sdk_1.updateComment)({ collaborationPath: collaborationPath, tenant: tenant, data: data })
            .then(function (comment) { return updateCommentInState(__assign(__assign({}, comment), { replies: replies })); })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, tenant]);
    var deleteComment = (0, react_1.useCallback)(function (_a) {
        var uri = _a.uri, commentId = _a.commentId;
        setSending(true);
        (0, mdm_sdk_1.deleteComment)({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId })
            .then(function () { return deleteCommentFromState(commentId, uri); })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, tenant]);
    var updateReplyInState = (0, react_1.useCallback)(function (reply, uri, commentId, isDeleteReply) {
        var newStatus = reply.action === 'resolve' ? 'resolved' : 'open';
        var replyId = reply.replyId;
        if (newStatus === 'resolved') {
            setCurrentComment(function (prevCurrentComment) {
                if (prevCurrentComment) {
                    return null;
                }
            });
        }
        else {
            setCurrentComment(function (prevCurrentComment) {
                if (prevCurrentComment) {
                    return __assign(__assign({}, prevCurrentComment), { replies: isDeleteReply
                            ? filterReplies(replyId, prevCurrentComment.replies)
                            : __spreadArray(__spreadArray([], prevCurrentComment.replies, true), [reply], false) });
                }
            });
        }
        setCommentsMap(function (prevCommentsMap) {
            var _a;
            return (__assign(__assign({}, prevCommentsMap), (_a = {}, _a[uri] = (prevCommentsMap[uri] || []).map(function (comment) {
                if (comment.commentId === commentId) {
                    return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply ? comment.replies - 1 : comment.replies + 1 });
                }
                return comment;
            }), _a)));
        });
        setComments(function (prevComments) {
            return prevComments.map(function (comment) {
                if (comment.commentId === commentId) {
                    return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply
                            ? filterReplies(reply.replyId, comment.replies)
                            : __spreadArray(__spreadArray([], comment.replies, true), [reply], false) });
                }
                return comment;
            });
        });
        if (isDeleteReply) {
            setTotalCommentsCount(function (prevCount) { return Math.max((prevCount || 0) - 1, 0); });
        }
        else {
            setTotalCommentsCount(function (prevCount) { return (prevCount || 0) + 1; });
        }
    }, []);
    var deleteReply = (0, react_1.useCallback)(function (_a) {
        var uri = _a.uri, commentId = _a.commentId, reply = _a.reply;
        setSending(true);
        (0, mdm_sdk_1.deleteReply)({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: reply.replyId })
            .then(function () { return updateReplyInState(reply, uri, commentId, true); })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, updateReplyInState, tenant]);
    var editReplyInState = (0, react_1.useCallback)(function (reply, commentId) {
        setCurrentComment(function (prevCurrentComment) {
            if (prevCurrentComment) {
                return __assign(__assign({}, prevCurrentComment), { replies: getUpdatedReplies(prevCurrentComment, reply) });
            }
        });
        setComments(function (prevComments) {
            return prevComments.map(function (comment) {
                if (comment.commentId === commentId) {
                    return __assign(__assign({}, comment), { replies: getUpdatedReplies(comment, reply) });
                }
                return comment;
            });
        });
    }, []);
    var editReply = (0, react_1.useCallback)(function (_a) {
        var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, replyId = _a.replyId;
        setSending(true);
        var data = {
            content: content,
            namedUsers: namedUsers
        };
        return (0, mdm_sdk_1.updateReply)({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: replyId, data: data })
            .then(function (reply) { return editReplyInState(reply, commentId); })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, tenant, editReplyInState]);
    var createReply = (0, react_1.useCallback)(function (_a) {
        var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, action = _a.action, uri = _a.uri;
        setSending(true);
        var data = {
            content: content,
            action: action,
            namedUsers: namedUsers
        };
        return (0, mdm_sdk_1.createReply)({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, data: data })
            .then(function (_a) {
            var reply = _a[0];
            return updateReplyInState(reply, uri, commentId);
        })
            .catch(catchErrorInRequest)
            .finally(function () { return setSending(false); });
    }, [collaborationPath, tenant, updateReplyInState]);
    var resolveThread = (0, react_1.useCallback)(function (_a) {
        var commentId = _a.commentId, uri = _a.uri;
        createReply({ content: '', namedUsers: [], commentId: commentId, action: 'resolve', uri: uri });
    }, [createReply]);
    var reOpenThread = (0, react_1.useCallback)(function (_a) {
        var commentId = _a.commentId, uri = _a.uri;
        createReply({ content: '', namedUsers: [], commentId: commentId, action: 'reopen', uri: uri });
    }, [createReply]);
    var clearCurrentComment = (0, react_1.useCallback)(function () {
        setCurrentComment(null);
    }, []);
    var getCommentState = (0, react_1.useCallback)(function (uri, commentUri) { return (0, ramda_1.pathOr)({}, [uri, commentUri], collaborationStateMap); }, [collaborationStateMap]);
    var clearCommentState = (0, react_1.useCallback)(function (uri, commentUri) { return setCollaborationStateMap((0, ramda_1.dissocPath)([uri, commentUri])); }, []);
    var updateCommentState = (0, react_1.useCallback)(function (uri, commentUri, newState) {
        setCollaborationStateMap(function (prevCollaborationStateMap) {
            var pathToCommentState = [uri, commentUri];
            var prevCommentState = (0, ramda_1.path)(pathToCommentState, prevCollaborationStateMap);
            return (0, ramda_1.assocPath)(pathToCommentState, (0, ramda_1.mergeRight)(prevCommentState, newState), prevCollaborationStateMap);
        });
    }, []);
    return (0, react_1.useMemo)(function () { return ({
        clearCurrentComment: clearCurrentComment,
        comments: comments,
        commentsMap: commentsMap,
        getCommentState: getCommentState,
        updateCommentState: updateCommentState,
        clearCommentState: clearCommentState,
        createComment: createComment,
        createReply: createReply,
        currentComment: currentComment,
        deleteComment: deleteComment,
        editComment: editComment,
        getComment: getComment,
        getComments: getComments,
        getCommentsCount: getCommentsCount,
        loading: loading,
        objectTypes: objectTypes,
        pageToken: pageToken,
        reOpenThread: reOpenThread,
        resolveThread: resolveThread,
        sending: sending,
        deleteReply: deleteReply,
        editReply: editReply,
        totalCommentsCount: totalCommentsCount
    }); }, [
        clearCurrentComment,
        comments,
        commentsMap,
        getCommentState,
        updateCommentState,
        clearCommentState,
        createComment,
        createReply,
        currentComment,
        deleteComment,
        editComment,
        getComment,
        getComments,
        getCommentsCount,
        loading,
        objectTypes,
        pageToken,
        reOpenThread,
        resolveThread,
        sending,
        deleteReply,
        editReply,
        totalCommentsCount
    ]);
};
exports.useCollaboration = useCollaboration;
