// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { fromFlatCommunicationIdentifier } from "../../../acs-ui-common/src";
import memoizeOne from 'memoize-one';
/**
 * Create the default implementation of {@link ChatHandlers}.
 *
 * Useful when implementing a custom component that utilizes the providers
 * exported from this library.
 *
 * Returned object is memoized to avoid rerenders when used as props for React Components.
 *
 * @public
 */
export const createDefaultChatHandlers = memoizeOne((chatClient, chatThreadClient) => {
    let messageIterator = undefined;
    let readReceiptIterator = undefined;
    return {
        // due to a bug in babel, we can't use arrow function here
        // affecting conditional-compile-remove(attachment-upload)
        onSendMessage: function (content, options) {
            return __awaiter(this, void 0, void 0, function* () {
                const sendMessageRequest = {
                    content
                };
                yield chatThreadClient.sendMessage(sendMessageRequest, Object.assign(Object.assign({}, options), { senderDisplayName: chatClient.getState().displayName }));
            });
        },
        // due to a bug in babel, we can't use arrow function here
        // affecting conditional-compile-remove(attachment-upload)
        onUpdateMessage: function (messageId, content) {
            return __awaiter(this, void 0, void 0, function* () {
                const updateMessageOptions = {
                    content
                };
                yield chatThreadClient.updateMessage(messageId, updateMessageOptions);
            });
        },
        onDeleteMessage: (messageId) => __awaiter(void 0, void 0, void 0, function* () {
            yield chatThreadClient.deleteMessage(messageId);
        }),
        // This handler is designed for chatThread to consume
        onMessageSeen: (chatMessageId) => __awaiter(void 0, void 0, void 0, function* () {
            yield chatThreadClient.sendReadReceipt({
                chatMessageId
            });
        }),
        onTyping: () => __awaiter(void 0, void 0, void 0, function* () {
            yield chatThreadClient.sendTypingNotification();
        }),
        onRemoveParticipant: (userId) => __awaiter(void 0, void 0, void 0, function* () {
            yield chatThreadClient.removeParticipant(fromFlatCommunicationIdentifier(userId));
        }),
        updateThreadTopicName: (topicName) => __awaiter(void 0, void 0, void 0, function* () {
            yield chatThreadClient.updateTopic(topicName);
        }),
        onLoadPreviousChatMessages: (messagesToLoad) => __awaiter(void 0, void 0, void 0, function* () {
            var _a, _b, _c;
            if (messageIterator === undefined) {
                // Lazy definition so that errors in the method call are reported correctly.
                // Also allows recovery via retries in case of transient errors.
                messageIterator = chatThreadClient.listMessages({
                    maxPageSize: 50
                });
            }
            if (readReceiptIterator === undefined) {
                readReceiptIterator = chatThreadClient.listReadReceipts();
            }
            // get the earliest message time
            let remainingMessagesToGet = messagesToLoad;
            let isAllChatMessagesLoaded = false;
            let earliestTime = Number.MAX_SAFE_INTEGER;
            while (remainingMessagesToGet >= 1) {
                const message = yield messageIterator.next();
                if ((_a = message === null || message === void 0 ? void 0 : message.value) === null || _a === void 0 ? void 0 : _a.id) {
                    if (parseInt(message.value.id) < earliestTime) {
                        earliestTime = parseInt(message.value.id);
                    }
                }
                if (((_b = message.value) === null || _b === void 0 ? void 0 : _b.type) && message.value.type === 'text') {
                    remainingMessagesToGet--;
                }
                // We have traversed all messages in this thread
                if (message.done) {
                    isAllChatMessagesLoaded = true;
                    break;
                }
            }
            // keep fetching read receipts until read receipt time < earlist message time
            let readReceipt = yield readReceiptIterator.next();
            while (!readReceipt.done && parseInt((_c = readReceipt === null || readReceipt === void 0 ? void 0 : readReceipt.value) === null || _c === void 0 ? void 0 : _c.chatMessageId) >= earliestTime) {
                readReceipt = yield readReceiptIterator.next();
            }
            return isAllChatMessagesLoaded;
        })
    };
});
/**
 * Create a set of default handlers for given component.
 *
 * Returned object is memoized (with reference to the arguments) to avoid
 * renders when used as props for React Components.
 *
 * @public
 */
export const createDefaultChatHandlersForComponent = (chatClient, chatThreadClient, _) => {
    return createDefaultChatHandlers(chatClient, chatThreadClient);
};
//# sourceMappingURL=createHandlers.js.map