import clsx from 'clsx';
import React from 'react';
import { useEnrichedMessages, useMessageListElements, useScrollLocationLogic, useUnreadMessagesNotification, } from './hooks/MessageList';
import { useMarkRead } from './hooks/useMarkRead';
import { MessageNotification as DefaultMessageNotification } from './MessageNotification';
import { MessageListNotifications as DefaultMessageListNotifications } from './MessageListNotifications';
import { UnreadMessagesNotification as DefaultUnreadMessagesNotification } from './UnreadMessagesNotification';
import { useChannelActionContext, } from '../../context/ChannelActionContext';
import { useChannelStateContext, } from '../../context/ChannelStateContext';
import { useChatContext } from '../../context/ChatContext';
import { useComponentContext } from '../../context/ComponentContext';
import { MessageListContextProvider } from '../../context/MessageListContext';
import { EmptyStateIndicator as DefaultEmptyStateIndicator } from '../EmptyStateIndicator';
import { InfiniteScroll } from '../InfiniteScrollPaginator/InfiniteScroll';
import { LoadingIndicator as DefaultLoadingIndicator } from '../Loading';
import { defaultPinPermissions, MESSAGE_ACTIONS } from '../Message/utils';
import { TypingIndicator as DefaultTypingIndicator } from '../TypingIndicator';
import { MessageListMainPanel } from './MessageListMainPanel';
import { defaultRenderMessages } from './renderMessages';
import { DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, DEFAULT_NEXT_CHANNEL_PAGE_SIZE, } from '../../constants/limits';
const MessageListWithContext = (props) => {
    const { channel, channelUnreadUiState, disableDateSeparator = false, groupStyles, hideDeletedMessages = false, hideNewMessageSeparator = false, internalInfiniteScrollProps: { threshold: loadMoreScrollThreshold = DEFAULT_LOAD_PAGE_SCROLL_THRESHOLD, ...restInternalInfiniteScrollProps } = {}, maxTimeBetweenGroupedMessages, messageActions = Object.keys(MESSAGE_ACTIONS), messages = [], notifications, noGroupByUser = false, pinPermissions = defaultPinPermissions, // @deprecated in favor of `channelCapabilities` - TODO: remove in next major release
    returnAllReadData = false, threadList = false, unsafeHTML = false, headerPosition, read, renderMessages = defaultRenderMessages, reviewProcessedMessage, messageLimit = DEFAULT_NEXT_CHANNEL_PAGE_SIZE, loadMore: loadMoreCallback, loadMoreNewer: loadMoreNewerCallback, hasMoreNewer = false, reactionDetailsSort, showUnreadNotificationAlways, sortReactionDetails, sortReactions, suppressAutoscroll, highlightedMessageId, jumpToLatestMessage = () => Promise.resolve(), } = props;
    const [listElement, setListElement] = React.useState(null);
    const [ulElement, setUlElement] = React.useState(null);
    const { customClasses } = useChatContext('MessageList');
    const { EmptyStateIndicator = DefaultEmptyStateIndicator, LoadingIndicator = DefaultLoadingIndicator, MessageListNotifications = DefaultMessageListNotifications, MessageNotification = DefaultMessageNotification, TypingIndicator = DefaultTypingIndicator, UnreadMessagesNotification = DefaultUnreadMessagesNotification, } = useComponentContext('MessageList');
    const { hasNewMessages, isMessageListScrolledToBottom, onScroll, scrollToBottom, wrapperRect, } = useScrollLocationLogic({
        hasMoreNewer,
        listElement,
        loadMoreScrollThreshold,
        messages,
        scrolledUpThreshold: props.scrolledUpThreshold,
        suppressAutoscroll,
    });
    const { show: showUnreadMessagesNotification } = useUnreadMessagesNotification({
        isMessageListScrolledToBottom,
        showAlways: !!showUnreadNotificationAlways,
        unreadCount: channelUnreadUiState?.unread_messages,
    });
    useMarkRead({
        isMessageListScrolledToBottom,
        messageListIsThread: threadList,
        unreadCount: channelUnreadUiState?.unread_messages ?? 0,
        wasMarkedUnread: !!channelUnreadUiState?.first_unread_message_id,
    });
    const { messageGroupStyles, messages: enrichedMessages } = useEnrichedMessages({
        channel,
        disableDateSeparator,
        groupStyles,
        headerPosition,
        hideDeletedMessages,
        hideNewMessageSeparator,
        maxTimeBetweenGroupedMessages,
        messages,
        noGroupByUser,
        reviewProcessedMessage,
    });
    const elements = useMessageListElements({
        channelUnreadUiState,
        enrichedMessages,
        internalMessageProps: {
            additionalMessageInputProps: props.additionalMessageInputProps,
            closeReactionSelectorOnClick: props.closeReactionSelectorOnClick,
            customMessageActions: props.customMessageActions,
            disableQuotedMessages: props.disableQuotedMessages,
            formatDate: props.formatDate,
            getDeleteMessageErrorNotification: props.getDeleteMessageErrorNotification,
            getFlagMessageErrorNotification: props.getFlagMessageErrorNotification,
            getFlagMessageSuccessNotification: props.getFlagMessageSuccessNotification,
            getMarkMessageUnreadErrorNotification: props.getMarkMessageUnreadErrorNotification,
            getMarkMessageUnreadSuccessNotification: props.getMarkMessageUnreadSuccessNotification,
            getMuteUserErrorNotification: props.getMuteUserErrorNotification,
            getMuteUserSuccessNotification: props.getMuteUserSuccessNotification,
            getPinMessageErrorNotification: props.getPinMessageErrorNotification,
            Message: props.Message,
            messageActions,
            messageListRect: wrapperRect,
            onlySenderCanEdit: props.onlySenderCanEdit,
            onMentionsClick: props.onMentionsClick,
            onMentionsHover: props.onMentionsHover,
            onUserClick: props.onUserClick,
            onUserHover: props.onUserHover,
            openThread: props.openThread,
            pinPermissions,
            reactionDetailsSort,
            renderText: props.renderText,
            retrySendMessage: props.retrySendMessage,
            sortReactionDetails,
            sortReactions,
            unsafeHTML,
        },
        messageGroupStyles,
        read,
        renderMessages,
        returnAllReadData,
        threadList,
    });
    const messageListClass = customClasses?.messageList || 'str-chat__list';
    const loadMore = React.useCallback(() => {
        if (loadMoreCallback) {
            loadMoreCallback(messageLimit);
        }
    }, [loadMoreCallback, messageLimit]);
    const loadMoreNewer = React.useCallback(() => {
        if (loadMoreNewerCallback) {
            loadMoreNewerCallback(messageLimit);
        }
    }, [loadMoreNewerCallback, messageLimit]);
    const scrollToBottomFromNotification = React.useCallback(async () => {
        if (hasMoreNewer) {
            await jumpToLatestMessage();
        }
        else {
            scrollToBottom();
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [scrollToBottom, hasMoreNewer]);
    React.useLayoutEffect(() => {
        if (highlightedMessageId) {
            const element = ulElement?.querySelector(`[data-message-id='${highlightedMessageId}']`);
            element?.scrollIntoView({ block: 'center' });
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [highlightedMessageId]);
    const showEmptyStateIndicator = elements.length === 0 && !threadList;
    return (React.createElement(MessageListContextProvider, { value: { listElement, scrollToBottom } },
        React.createElement(MessageListMainPanel, null,
            !threadList && showUnreadMessagesNotification && (React.createElement(UnreadMessagesNotification, { unreadCount: channelUnreadUiState?.unread_messages })),
            React.createElement("div", { className: clsx(messageListClass, customClasses?.threadList), onScroll: onScroll, ref: setListElement, tabIndex: 0 }, showEmptyStateIndicator ? (React.createElement(EmptyStateIndicator, { listType: threadList ? 'thread' : 'message' })) : (React.createElement(InfiniteScroll, { className: 'str-chat__message-list-scroll', "data-testid": 'reverse-infinite-scroll', hasNextPage: props.hasMoreNewer, hasPreviousPage: props.hasMore, head: props.head, isLoading: props.loadingMore, loader: React.createElement("div", { className: 'str-chat__list__loading', key: 'loading-indicator' }, props.loadingMore && React.createElement(LoadingIndicator, { size: 20 })), loadNextPage: loadMoreNewer, loadPreviousPage: loadMore, threshold: loadMoreScrollThreshold, ...restInternalInfiniteScrollProps },
                React.createElement("ul", { className: 'str-chat__ul', ref: setUlElement }, elements),
                React.createElement(TypingIndicator, { threadList: threadList }),
                React.createElement("div", { key: 'bottom' }))))),
        React.createElement(MessageListNotifications, { hasNewMessages: hasNewMessages, isMessageListScrolledToBottom: isMessageListScrolledToBottom, isNotAtLatestMessageSet: hasMoreNewer, MessageNotification: MessageNotification, notifications: notifications, scrollToBottom: scrollToBottomFromNotification, threadList: threadList, unreadCount: threadList ? undefined : channelUnreadUiState?.unread_messages })));
};
/**
 * The MessageList component renders a list of Messages.
 * It is a consumer of the following contexts:
 * - [ChannelStateContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_state_context/)
 * - [ChannelActionContext](https://getstream.io/chat/docs/sdk/react/contexts/channel_action_context/)
 * - [ComponentContext](https://getstream.io/chat/docs/sdk/react/contexts/component_context/)
 * - [TypingContext](https://getstream.io/chat/docs/sdk/react/contexts/typing_context/)
 */
export const MessageList = (props) => {
    const { jumpToLatestMessage, loadMore, loadMoreNewer, } = useChannelActionContext('MessageList');
    const { members: membersPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
    mutes: mutesPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
    watchers: watchersPropToNotPass, // eslint-disable-line @typescript-eslint/no-unused-vars
    ...restChannelStateContext } = useChannelStateContext('MessageList');
    return (React.createElement(MessageListWithContext, { jumpToLatestMessage: jumpToLatestMessage, loadMore: loadMore, loadMoreNewer: loadMoreNewer, ...restChannelStateContext, ...props }));
};
