'use strict';

var React = require('react');
var index = require('./index-358554d2.js');
var utils_message_getOutgoingMessageState = require('./utils/message/getOutgoingMessageState.js');
var UserProfileContext = require('./UserProfileContext-2ff8462c.js');
var useSendbirdStateContext = require('./useSendbirdStateContext.js');
var _rollupPluginBabelHelpers = require('./_rollupPluginBabelHelpers-ea66c137.js');
var Thread_context_types = require('./Thread/context/types.js');
var SendbirdChat = require('@sendbird/chat');
var topics = require('./topics-2fe6fef6.js');
var groupChannel = require('@sendbird/chat/groupChannel');
var uuid = require('./uuid-f1d9be11.js');
var message = require('@sendbird/chat/message');
var consts = require('./consts-a6f34df8.js');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var React__default = /*#__PURE__*/_interopDefaultLegacy(React);

const getNicknamesMapFromMembers = function () {
  let members = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  const nicknamesMap = new Map();
  for (let memberIndex = 0; memberIndex < members.length; memberIndex += 1) {
    const {
      userId,
      nickname
    } = members[memberIndex];
    nicknamesMap.set(userId, nickname);
  }
  return nicknamesMap;
};
const getParentMessageFrom = message => {
  if (!message) {
    return null;
  }
  if (isParentMessage(message)) {
    return message;
  }
  if (isThreadMessage(message)) {
    return (message === null || message === void 0 ? void 0 : message.parentMessage) || null;
  }
  return null;
};
const isParentMessage = message => {
  return (message === null || message === void 0 ? void 0 : message.parentMessage) === null && typeof (message === null || message === void 0 ? void 0 : message.parentMessageId) === 'number' && !(message !== null && message !== void 0 && message.parentMessageId);
};
const isThreadMessage = message => {
  return (message === null || message === void 0 ? void 0 : message.parentMessage) !== null && typeof (message === null || message === void 0 ? void 0 : message.parentMessageId) === 'number' && (message === null || message === void 0 ? void 0 : message.parentMessageId) > 0 && (message === null || message === void 0 ? void 0 : message.threadInfo) === null;
};
const isAboutSame = (a, b, px) => Math.abs(a - b) <= px;
const isEmpty = val => val === null || val === undefined;

// Some Ids return string and number inconsistently
// only use to comapre IDs
function compareIds(a, b) {
  if (isEmpty(a) || isEmpty(b)) {
    return false;
  }
  const aString = a.toString();
  const bString = b.toString();
  return aString === bString;
}
const getMessageCreatedAt = message => index.format(message.createdAt, 'p');
const isReadMessage = (channel, message) => utils_message_getOutgoingMessageState.getOutgoingMessageState(channel, message) === utils_message_getOutgoingMessageState.OutgoingMessageStates.READ;
const isSameGroup = (message, comparingMessage, currentChannel) => {
  var _message$sender, _comparingMessage$sen, _message$sender2, _comparingMessage$sen2;
  if (!(message && comparingMessage && message.messageType && message.messageType !== 'admin' && comparingMessage.messageType && (comparingMessage === null || comparingMessage === void 0 ? void 0 : comparingMessage.messageType) !== 'admin' && message !== null && message !== void 0 && message.sender && comparingMessage !== null && comparingMessage !== void 0 && comparingMessage.sender && message !== null && message !== void 0 && message.createdAt && comparingMessage !== null && comparingMessage !== void 0 && comparingMessage.createdAt && message !== null && message !== void 0 && (_message$sender = message.sender) !== null && _message$sender !== void 0 && _message$sender.userId && comparingMessage !== null && comparingMessage !== void 0 && (_comparingMessage$sen = comparingMessage.sender) !== null && _comparingMessage$sen !== void 0 && _comparingMessage$sen.userId)) {
    return false;
  }
  return (message === null || message === void 0 ? void 0 : message.sendingStatus) === (comparingMessage === null || comparingMessage === void 0 ? void 0 : comparingMessage.sendingStatus) && (message === null || message === void 0 ? void 0 : (_message$sender2 = message.sender) === null || _message$sender2 === void 0 ? void 0 : _message$sender2.userId) === (comparingMessage === null || comparingMessage === void 0 ? void 0 : (_comparingMessage$sen2 = comparingMessage.sender) === null || _comparingMessage$sen2 === void 0 ? void 0 : _comparingMessage$sen2.userId) && getMessageCreatedAt(message) === getMessageCreatedAt(comparingMessage) && isReadMessage(currentChannel, message) === isReadMessage(currentChannel, comparingMessage);
};
const compareMessagesForGrouping = (prevMessage, currMessage, nextMessage, currentChannel, replyType) => {
  if (replyType === 'THREAD' && currMessage !== null && currMessage !== void 0 && currMessage.threadInfo) {
    return [false, false];
  }
  const sendingStatus = (currMessage === null || currMessage === void 0 ? void 0 : currMessage.sendingStatus) || '';
  const isAcceptable = sendingStatus !== 'pending' && sendingStatus !== 'failed';
  return [isSameGroup(prevMessage, currMessage, currentChannel) && isAcceptable, isSameGroup(currMessage, nextMessage, currentChannel) && isAcceptable];
};
const scrollIntoLast = function () {
  let intialTry = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  const MAX_TRIES = 10;
  const currentTry = intialTry;
  if (currentTry > MAX_TRIES) {
    return;
  }
  try {
    const scrollDOM = document.querySelector('.sendbird-thread-ui--scroll');
    // eslint-disable-next-line no-multi-assign
    scrollDOM.scrollTop = scrollDOM.scrollHeight;
  } catch (error) {
    setTimeout(() => {
      scrollIntoLast(currentTry + 1);
    }, 500 * currentTry);
  }
};

const PREV_THREADS_FETCH_SIZE = 30;
const NEXT_THREADS_FETCH_SIZE = 30;

let ThreadContextActionTypes = /*#__PURE__*/function (ThreadContextActionTypes) {
  ThreadContextActionTypes["INIT_USER_ID"] = "INIT_USER_ID";
  ThreadContextActionTypes["GET_CHANNEL_START"] = "GET_CHANNEL_START";
  ThreadContextActionTypes["GET_CHANNEL_SUCCESS"] = "GET_CHANNEL_SUCCESS";
  ThreadContextActionTypes["GET_CHANNEL_FAILURE"] = "GET_CHANNEL_FAILURE";
  ThreadContextActionTypes["SET_EMOJI_CONTAINER"] = "SET_EMOJI_CONTAINER";
  ThreadContextActionTypes["GET_PARENT_MESSAGE_START"] = "GET_PARENT_MESSAGE_START";
  ThreadContextActionTypes["GET_PARENT_MESSAGE_SUCCESS"] = "GET_PARENT_MESSAGE_SUCCESS";
  ThreadContextActionTypes["GET_PARENT_MESSAGE_FAILURE"] = "GET_PARENT_MESSAGE_FAILURE";
  ThreadContextActionTypes["INITIALIZE_THREAD_LIST_START"] = "INITIALIZE_THREAD_LIST_START";
  ThreadContextActionTypes["INITIALIZE_THREAD_LIST_SUCCESS"] = "INITIALIZE_THREAD_LIST_SUCCESS";
  ThreadContextActionTypes["INITIALIZE_THREAD_LIST_FAILURE"] = "INITIALIZE_THREAD_LIST_FAILURE";
  ThreadContextActionTypes["GET_PREV_MESSAGES_START"] = "GET_PREV_MESSAGES_START";
  ThreadContextActionTypes["GET_PREV_MESSAGES_SUCESS"] = "GET_PREV_MESSAGES_SUCESS";
  ThreadContextActionTypes["GET_PREV_MESSAGES_FAILURE"] = "GET_PREV_MESSAGES_FAILURE";
  ThreadContextActionTypes["GET_NEXT_MESSAGES_START"] = "GET_NEXT_MESSAGES_START";
  ThreadContextActionTypes["GET_NEXT_MESSAGES_SUCESS"] = "GET_NEXT_MESSAGES_SUCESS";
  ThreadContextActionTypes["GET_NEXT_MESSAGES_FAILURE"] = "GET_NEXT_MESSAGES_FAILURE";
  ThreadContextActionTypes["SEND_MESSAGE_START"] = "SEND_MESSAGE_START";
  ThreadContextActionTypes["SEND_MESSAGE_SUCESS"] = "SEND_MESSAGE_SUCESS";
  ThreadContextActionTypes["SEND_MESSAGE_FAILURE"] = "SEND_MESSAGE_FAILURE";
  ThreadContextActionTypes["RESEND_MESSAGE_START"] = "RESEND_MESSAGE_START";
  ThreadContextActionTypes["ON_MESSAGE_DELETED_BY_REQ_ID"] = "ON_MESSAGE_DELETED_BY_REQ_ID";
  ThreadContextActionTypes["ON_MESSAGE_RECEIVED"] = "ON_MESSAGE_RECEIVED";
  ThreadContextActionTypes["ON_MESSAGE_UPDATED"] = "ON_MESSAGE_UPDATED";
  ThreadContextActionTypes["ON_MESSAGE_DELETED"] = "ON_MESSAGE_DELETED";
  ThreadContextActionTypes["ON_REACTION_UPDATED"] = "ON_REACTION_UPDATED";
  ThreadContextActionTypes["ON_USER_MUTED"] = "ON_USER_MUTED";
  ThreadContextActionTypes["ON_USER_UNMUTED"] = "ON_USER_UNMUTED";
  ThreadContextActionTypes["ON_USER_BANNED"] = "ON_USER_BANNED";
  ThreadContextActionTypes["ON_USER_UNBANNED"] = "ON_USER_UNBANNED";
  ThreadContextActionTypes["ON_USER_LEFT"] = "ON_USER_LEFT";
  ThreadContextActionTypes["ON_CHANNEL_FROZEN"] = "ON_CHANNEL_FROZEN";
  ThreadContextActionTypes["ON_CHANNEL_UNFROZEN"] = "ON_CHANNEL_UNFROZEN";
  ThreadContextActionTypes["ON_OPERATOR_UPDATED"] = "ON_OPERATOR_UPDATED";
  return ThreadContextActionTypes;
}({});

function reducer(state, action) {
  switch (action.type) {
    // initialize
    case ThreadContextActionTypes.INIT_USER_ID:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          currentUserId: action.payload
        });
      }
    case ThreadContextActionTypes.GET_CHANNEL_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          channelState: Thread_context_types.ChannelStateTypes.LOADING,
          currentChannel: null
        });
      }
    case ThreadContextActionTypes.GET_CHANNEL_SUCCESS:
      {
        var _groupChannel$members, _groupChannel$members2;
        const groupChannel = action.payload.groupChannel;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          channelState: Thread_context_types.ChannelStateTypes.INITIALIZED,
          currentChannel: groupChannel,
          // only support in normal group channel
          isMuted: (groupChannel === null || groupChannel === void 0 ? void 0 : (_groupChannel$members = groupChannel.members) === null || _groupChannel$members === void 0 ? void 0 : (_groupChannel$members2 = _groupChannel$members.find(member => (member === null || member === void 0 ? void 0 : member.userId) === state.currentUserId)) === null || _groupChannel$members2 === void 0 ? void 0 : _groupChannel$members2.isMuted) || false,
          isChannelFrozen: (groupChannel === null || groupChannel === void 0 ? void 0 : groupChannel.isFrozen) || false
        });
      }
    case ThreadContextActionTypes.GET_CHANNEL_FAILURE:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          channelState: Thread_context_types.ChannelStateTypes.INVALID,
          currentChannel: null
        });
      }
    case ThreadContextActionTypes.SET_EMOJI_CONTAINER:
      {
        const {
          emojiContainer
        } = action.payload;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          emojiContainer: emojiContainer
        });
      }
    case ThreadContextActionTypes.GET_PARENT_MESSAGE_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          parentMessageState: Thread_context_types.ParentMessageStateTypes.LOADING,
          parentMessage: null
        });
      }
    case ThreadContextActionTypes.GET_PARENT_MESSAGE_SUCCESS:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          parentMessageState: Thread_context_types.ParentMessageStateTypes.INITIALIZED,
          parentMessage: action.payload.parentMessage
        });
      }
    case ThreadContextActionTypes.GET_PARENT_MESSAGE_FAILURE:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          parentMessageState: Thread_context_types.ParentMessageStateTypes.INVALID,
          parentMessage: null
        });
      }
    // fetch threads
    case ThreadContextActionTypes.INITIALIZE_THREAD_LIST_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          threadListState: Thread_context_types.ThreadListStateTypes.LOADING,
          allThreadMessages: []
        });
      }
    case ThreadContextActionTypes.INITIALIZE_THREAD_LIST_SUCCESS:
      {
        const {
          parentMessage,
          anchorMessage,
          threadedMessages
        } = action.payload;
        const anchorMessageCreatedAt = !(anchorMessage !== null && anchorMessage !== void 0 && anchorMessage.messageId) ? parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.createdAt : anchorMessage === null || anchorMessage === void 0 ? void 0 : anchorMessage.createdAt;
        const anchorIndex = threadedMessages.findIndex(message => (message === null || message === void 0 ? void 0 : message.createdAt) > anchorMessageCreatedAt);
        const prevThreadMessages = anchorIndex > -1 ? threadedMessages.slice(0, anchorIndex) : threadedMessages;
        const anchorThreadMessage = anchorMessage !== null && anchorMessage !== void 0 && anchorMessage.messageId ? [anchorMessage] : [];
        const nextThreadMessages = anchorIndex > -1 ? threadedMessages.slice(anchorIndex) : [];
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          threadListState: Thread_context_types.ThreadListStateTypes.INITIALIZED,
          hasMorePrev: anchorIndex === -1 || anchorIndex === PREV_THREADS_FETCH_SIZE,
          hasMoreNext: threadedMessages.length - anchorIndex === NEXT_THREADS_FETCH_SIZE,
          allThreadMessages: [prevThreadMessages, anchorThreadMessage, nextThreadMessages].flat()
        });
      }
    case ThreadContextActionTypes.INITIALIZE_THREAD_LIST_FAILURE:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          threadListState: Thread_context_types.ThreadListStateTypes.INVALID,
          allThreadMessages: []
        });
      }
    case ThreadContextActionTypes.GET_NEXT_MESSAGES_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2({}, state);
      }
    case ThreadContextActionTypes.GET_NEXT_MESSAGES_SUCESS:
      {
        const {
          threadedMessages
        } = action.payload;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          hasMoreNext: threadedMessages.length === NEXT_THREADS_FETCH_SIZE,
          allThreadMessages: [...state.allThreadMessages, ...threadedMessages]
        });
      }
    case ThreadContextActionTypes.GET_NEXT_MESSAGES_FAILURE:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          hasMoreNext: false
        });
      }
    case ThreadContextActionTypes.GET_PREV_MESSAGES_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2({}, state);
      }
    case ThreadContextActionTypes.GET_PREV_MESSAGES_SUCESS:
      {
        const {
          threadedMessages
        } = action.payload;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          hasMorePrev: threadedMessages.length === PREV_THREADS_FETCH_SIZE,
          allThreadMessages: [...threadedMessages, ...state.allThreadMessages]
        });
      }
    case ThreadContextActionTypes.GET_PREV_MESSAGES_FAILURE:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          hasMorePrev: false
        });
      }
    // event handlers - message status change
    case ThreadContextActionTypes.ON_MESSAGE_RECEIVED:
      {
        var _state$currentChannel, _message$parentMessag, _state$parentMessage, _state$parentMessage2;
        const {
          channel,
          message
        } = action.payload;
        if (((_state$currentChannel = state.currentChannel) === null || _state$currentChannel === void 0 ? void 0 : _state$currentChannel.url) !== (channel === null || channel === void 0 ? void 0 : channel.url) || state.hasMoreNext || (message === null || message === void 0 ? void 0 : (_message$parentMessag = message.parentMessage) === null || _message$parentMessag === void 0 ? void 0 : _message$parentMessag.messageId) !== (state === null || state === void 0 ? void 0 : (_state$parentMessage = state.parentMessage) === null || _state$parentMessage === void 0 ? void 0 : _state$parentMessage.messageId)) {
          return state;
        }
        const isAlreadyReceived = state.allThreadMessages.findIndex(m => m.messageId === message.messageId) > -1;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          parentMessage: ((_state$parentMessage2 = state.parentMessage) === null || _state$parentMessage2 === void 0 ? void 0 : _state$parentMessage2.messageId) === (message === null || message === void 0 ? void 0 : message.messageId) ? message : state.parentMessage,
          allThreadMessages: isAlreadyReceived ? state.allThreadMessages.map(m => m.messageId === message.messageId ? message : m) : [...state.allThreadMessages.filter(m => (m === null || m === void 0 ? void 0 : m.reqId) !== (message === null || message === void 0 ? void 0 : message.reqId)), message]
        });
      }
    case ThreadContextActionTypes.ON_MESSAGE_UPDATED:
      {
        var _state$currentChannel2, _state$parentMessage3, _state$allThreadMessa;
        const {
          channel,
          message
        } = action.payload;
        if (((_state$currentChannel2 = state.currentChannel) === null || _state$currentChannel2 === void 0 ? void 0 : _state$currentChannel2.url) !== (channel === null || channel === void 0 ? void 0 : channel.url)) {
          return state;
        }
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          parentMessage: ((_state$parentMessage3 = state.parentMessage) === null || _state$parentMessage3 === void 0 ? void 0 : _state$parentMessage3.messageId) === (message === null || message === void 0 ? void 0 : message.messageId) ? message : state.parentMessage,
          allThreadMessages: (_state$allThreadMessa = state.allThreadMessages) === null || _state$allThreadMessa === void 0 ? void 0 : _state$allThreadMessa.map(msg => (msg === null || msg === void 0 ? void 0 : msg.messageId) === (message === null || message === void 0 ? void 0 : message.messageId) ? message : msg)
        });
      }
    case ThreadContextActionTypes.ON_MESSAGE_DELETED:
      {
        var _state$currentChannel3, _state$parentMessage4, _state$allThreadMessa2;
        const {
          channel,
          messageId
        } = action.payload;
        if (((_state$currentChannel3 = state.currentChannel) === null || _state$currentChannel3 === void 0 ? void 0 : _state$currentChannel3.url) !== (channel === null || channel === void 0 ? void 0 : channel.url)) {
          return state;
        }
        if ((state === null || state === void 0 ? void 0 : (_state$parentMessage4 = state.parentMessage) === null || _state$parentMessage4 === void 0 ? void 0 : _state$parentMessage4.messageId) === messageId) {
          return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
            parentMessage: null,
            parentMessageState: Thread_context_types.ParentMessageStateTypes.NIL,
            allThreadMessages: []
          });
        }
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: (_state$allThreadMessa2 = state.allThreadMessages) === null || _state$allThreadMessa2 === void 0 ? void 0 : _state$allThreadMessa2.filter(msg => (msg === null || msg === void 0 ? void 0 : msg.messageId) !== messageId)
        });
      }
    case ThreadContextActionTypes.ON_MESSAGE_DELETED_BY_REQ_ID:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: state.allThreadMessages.filter(m => !compareIds(m.reqId, action.payload))
        });
      }
    case ThreadContextActionTypes.ON_REACTION_UPDATED:
      {
        var _action$payload, _state$parentMessage5;
        const reactionEvent = (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : _action$payload.reactionEvent;
        if ((state === null || state === void 0 ? void 0 : (_state$parentMessage5 = state.parentMessage) === null || _state$parentMessage5 === void 0 ? void 0 : _state$parentMessage5.messageId) === (reactionEvent === null || reactionEvent === void 0 ? void 0 : reactionEvent.messageId)) {
          var _state$parentMessage6, _state$parentMessage7;
          (_state$parentMessage6 = state.parentMessage) === null || _state$parentMessage6 === void 0 ? void 0 : (_state$parentMessage7 = _state$parentMessage6.applyReactionEvent) === null || _state$parentMessage7 === void 0 ? void 0 : _state$parentMessage7.call(_state$parentMessage6, reactionEvent);
        }
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: state.allThreadMessages.map(m => {
            if ((reactionEvent === null || reactionEvent === void 0 ? void 0 : reactionEvent.messageId) === (m === null || m === void 0 ? void 0 : m.messageId)) {
              var _m$applyReactionEvent;
              m === null || m === void 0 ? void 0 : (_m$applyReactionEvent = m.applyReactionEvent) === null || _m$applyReactionEvent === void 0 ? void 0 : _m$applyReactionEvent.call(m, reactionEvent);
              return m;
            }
            return m;
          })
        });
      }
    // event handlers - user status change
    case ThreadContextActionTypes.ON_USER_MUTED:
      {
        var _state$currentChannel4;
        const {
          channel,
          user
        } = action.payload;
        if (((_state$currentChannel4 = state.currentChannel) === null || _state$currentChannel4 === void 0 ? void 0 : _state$currentChannel4.url) !== (channel === null || channel === void 0 ? void 0 : channel.url) || state.currentUserId !== (user === null || user === void 0 ? void 0 : user.userId)) {
          return state;
        }
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          isMuted: true
        });
      }
    case ThreadContextActionTypes.ON_USER_UNMUTED:
      {
        var _state$currentChannel5;
        const {
          channel,
          user
        } = action.payload;
        if (((_state$currentChannel5 = state.currentChannel) === null || _state$currentChannel5 === void 0 ? void 0 : _state$currentChannel5.url) !== (channel === null || channel === void 0 ? void 0 : channel.url) || state.currentUserId !== (user === null || user === void 0 ? void 0 : user.userId)) {
          return state;
        }
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          isMuted: false
        });
      }
    case ThreadContextActionTypes.ON_USER_BANNED:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          channelState: Thread_context_types.ChannelStateTypes.NIL,
          threadListState: Thread_context_types.ThreadListStateTypes.NIL,
          parentMessageState: Thread_context_types.ParentMessageStateTypes.NIL,
          currentChannel: null,
          parentMessage: null,
          allThreadMessages: [],
          hasMorePrev: false,
          hasMoreNext: false
        });
      }
    case ThreadContextActionTypes.ON_USER_UNBANNED:
      {
        return _rollupPluginBabelHelpers._objectSpread2({}, state);
      }
    case ThreadContextActionTypes.ON_USER_LEFT:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          channelState: Thread_context_types.ChannelStateTypes.NIL,
          threadListState: Thread_context_types.ThreadListStateTypes.NIL,
          parentMessageState: Thread_context_types.ParentMessageStateTypes.NIL,
          currentChannel: null,
          parentMessage: null,
          allThreadMessages: [],
          hasMorePrev: false,
          hasMoreNext: false
        });
      }
    // event handler - channel status change
    case ThreadContextActionTypes.ON_CHANNEL_FROZEN:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          isChannelFrozen: true
        });
      }
    case ThreadContextActionTypes.ON_CHANNEL_UNFROZEN:
      {
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          isChannelFrozen: false
        });
      }
    case ThreadContextActionTypes.ON_OPERATOR_UPDATED:
      {
        var _state$currentChannel6;
        const {
          channel
        } = action.payload;
        if ((channel === null || channel === void 0 ? void 0 : channel.url) === ((_state$currentChannel6 = state.currentChannel) === null || _state$currentChannel6 === void 0 ? void 0 : _state$currentChannel6.url)) {
          return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
            currentChannel: channel
          });
        }
        return state;
      }
    // message
    case ThreadContextActionTypes.SEND_MESSAGE_START:
      {
        const {
          message
        } = action.payload;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: [...state.allThreadMessages, message]
        });
      }
    case ThreadContextActionTypes.SEND_MESSAGE_SUCESS:
      {
        const {
          message
        } = action.payload;
        const filteredThreadMessages = state.allThreadMessages.filter(m => !compareIds(m === null || m === void 0 ? void 0 : m.reqId, message === null || message === void 0 ? void 0 : message.reqId));
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: [...filteredThreadMessages, message]
        });
      }
    case ThreadContextActionTypes.SEND_MESSAGE_FAILURE:
      {
        const {
          message
        } = action.payload;
        return _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, state), {}, {
          allThreadMessages: state.allThreadMessages.map(m => compareIds(m === null || m === void 0 ? void 0 : m.reqId, message === null || message === void 0 ? void 0 : message.reqId) ? message : m)
        });
      }
    case ThreadContextActionTypes.RESEND_MESSAGE_START:
      {
        return _rollupPluginBabelHelpers._objectSpread2({}, state);
      }
    default:
      {
        return state;
      }
  }
}

const initialState = {
  currentChannel: null,
  allThreadMessages: [],
  parentMessage: null,
  channelState: Thread_context_types.ChannelStateTypes.NIL,
  parentMessageState: Thread_context_types.ParentMessageStateTypes.NIL,
  threadListState: Thread_context_types.ThreadListStateTypes.NIL,
  hasMorePrev: false,
  hasMoreNext: false,
  emojiContainer: {},
  isMuted: false,
  isChannelFrozen: false,
  currentUserId: ''
};

function useGetChannel(_ref, _ref2) {
  let {
    channelUrl,
    sdkInit,
    message
  } = _ref;
  let {
    sdk,
    logger,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    // validation check
    if (sdkInit && channelUrl && sdk !== null && sdk !== void 0 && sdk.groupChannel) {
      var _sdk$groupChannel$get, _sdk$groupChannel;
      threadDispatcher({
        type: ThreadContextActionTypes.GET_CHANNEL_START,
        payload: null
      });
      (_sdk$groupChannel$get = (_sdk$groupChannel = sdk.groupChannel).getChannel) === null || _sdk$groupChannel$get === void 0 ? void 0 : _sdk$groupChannel$get.call(_sdk$groupChannel, channelUrl).then(groupChannel => {
        logger.info('Thread | useInitialize: Get channel succeeded', groupChannel);
        threadDispatcher({
          type: ThreadContextActionTypes.GET_CHANNEL_SUCCESS,
          payload: {
            groupChannel
          }
        });
      }).catch(error => {
        logger.info('Thread | useInitialize: Get channel failed', error);
        threadDispatcher({
          type: ThreadContextActionTypes.GET_CHANNEL_FAILURE,
          payload: error
        });
      });
    }
  }, [message, sdkInit]);
  /**
   * We don't use channelUrl here,
   * because Thread must operate independently of the channel.
   */
}

function useGetAllEmoji(_ref, _ref2) {
  let {
    sdk
  } = _ref;
  let {
    logger,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    if (sdk !== null && sdk !== void 0 && sdk.getAllEmoji) {
      // validation check
      sdk === null || sdk === void 0 ? void 0 : sdk.getAllEmoji().then(emojiContainer => {
        logger.info('Thread | useGetAllEmoji: Getting emojis succeeded.', emojiContainer);
        threadDispatcher({
          type: ThreadContextActionTypes.SET_EMOJI_CONTAINER,
          payload: {
            emojiContainer
          }
        });
      }).catch(error => {
        logger.info('Thread | useGetAllEmoji: Getting emojis failed.', error);
      });
    }
  }, [sdk]);
}

function useGetThreadList(_ref, _ref2) {
  let {
    sdkInit,
    parentMessage,
    anchorMessage,
    isReactionEnabled
  } = _ref;
  let {
    logger,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    // validation check
    if (sdkInit && parentMessage !== null && parentMessage !== void 0 && parentMessage.getThreadedMessagesByTimestamp) {
      var _parentMessage$getThr;
      threadDispatcher({
        type: ThreadContextActionTypes.INITIALIZE_THREAD_LIST_START,
        payload: null
      });
      const timeStamp = (anchorMessage === null || anchorMessage === void 0 ? void 0 : anchorMessage.createdAt) || 0;
      const params = {
        prevResultSize: PREV_THREADS_FETCH_SIZE,
        nextResultSize: NEXT_THREADS_FETCH_SIZE,
        includeReactions: isReactionEnabled,
        includeMetaArray: true
      };
      logger.info('Thread | useGetThreadList: Initialize thread list start.', {
        timeStamp,
        params
      });
      (_parentMessage$getThr = parentMessage.getThreadedMessagesByTimestamp) === null || _parentMessage$getThr === void 0 ? void 0 : _parentMessage$getThr.call(parentMessage, timeStamp, params).then(_ref3 => {
        let {
          parentMessage,
          threadedMessages
        } = _ref3;
        logger.info('Thread | useGetThreadList: Initialize thread list succeeded.', {
          parentMessage,
          threadedMessages
        });
        threadDispatcher({
          type: ThreadContextActionTypes.INITIALIZE_THREAD_LIST_SUCCESS,
          payload: {
            parentMessage,
            anchorMessage,
            threadedMessages
          }
        });
      }).catch(error => {
        logger.info('Therad | useGetThreadList: Initialize thread list failed.', error);
        threadDispatcher({
          type: ThreadContextActionTypes.INITIALIZE_THREAD_LIST_FAILURE,
          payload: error
        });
      });
    }
  }, [sdkInit, parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.messageId, anchorMessage]);
}

function useGetParentMessage(_ref, _ref2) {
  let {
    channelUrl,
    sdkInit,
    parentMessage
  } = _ref;
  let {
    sdk,
    logger,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    var _sdk$message;
    // validation check
    if (sdkInit && sdk !== null && sdk !== void 0 && (_sdk$message = sdk.message) !== null && _sdk$message !== void 0 && _sdk$message.getMessage) {
      threadDispatcher({
        type: ThreadContextActionTypes.GET_PARENT_MESSAGE_START,
        payload: null
      });
      const params = {
        channelUrl,
        channelType: SendbirdChat.ChannelType.GROUP,
        messageId: parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.messageId,
        includeMetaArray: true,
        includeReactions: true,
        includeThreadInfo: true,
        includeParentMessageInfo: true
      };
      logger.info('Thread | useGetParentMessage: Get parent message start.', params);
      const fetchParentMessage = async () => {
        var _sdk$message$getMessa, _sdk$message2;
        const data = await ((_sdk$message$getMessa = (_sdk$message2 = sdk.message).getMessage) === null || _sdk$message$getMessa === void 0 ? void 0 : _sdk$message$getMessa.call(_sdk$message2, params));
        return data;
      };
      fetchParentMessage().then(parentMsg => {
        logger.info('Thread | useGetParentMessage: Get parent message succeeded.', parentMessage);
        parentMsg.ogMetaData = (parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.ogMetaData) || null; // ogMetaData is not included for now
        threadDispatcher({
          type: ThreadContextActionTypes.GET_PARENT_MESSAGE_SUCCESS,
          payload: {
            parentMessage: parentMsg
          }
        });
      }).catch(error => {
        logger.info('Thread | useGetParentMessage: Get parent message failed.', error);
        threadDispatcher({
          type: ThreadContextActionTypes.GET_PARENT_MESSAGE_FAILURE,
          payload: error
        });
      });
    }
  }, [sdkInit, parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.messageId]);
  /**
   * We don't use channelUrl here,
   * because Thread must operate independently of the channel.
   */
}

function useHandlePubsubEvents(_ref, _ref2) {
  let {
    sdkInit,
    currentChannel,
    parentMessage
  } = _ref;
  let {
    pubSub,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    const pubSubHandler = () => {
      const subscriber = new Map();
      if (!pubSub || !pubSub.subscribe) {
        return subscriber;
      }
      subscriber.set(topics.PUBSUB_TOPICS.SEND_USER_MESSAGE, pubSub.subscribe(topics.PUBSUB_TOPICS.SEND_USER_MESSAGE, props => {
        const {
          channel,
          message
        } = props;
        if ((currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.url) === (channel === null || channel === void 0 ? void 0 : channel.url) && (message === null || message === void 0 ? void 0 : message.parentMessageId) === (parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.messageId)) {
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_SUCESS,
            payload: {
              message
            }
          });
        }
        scrollIntoLast === null || scrollIntoLast === void 0 ? void 0 : scrollIntoLast();
      }));
      subscriber.set(topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, pubSub.subscribe(topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, props => {
        const {
          channel,
          message
        } = props;
        if ((currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.url) === (channel === null || channel === void 0 ? void 0 : channel.url)) {
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_SUCESS,
            payload: {
              message
            }
          });
        }
        scrollIntoLast === null || scrollIntoLast === void 0 ? void 0 : scrollIntoLast();
      }));
      subscriber.set(topics.PUBSUB_TOPICS.UPDATE_USER_MESSAGE, pubSub.subscribe(topics.PUBSUB_TOPICS.UPDATE_USER_MESSAGE, msg => {
        const {
          channel,
          message
        } = msg;
        if ((currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.url) === (channel === null || channel === void 0 ? void 0 : channel.url)) {
          threadDispatcher({
            type: ThreadContextActionTypes.ON_MESSAGE_UPDATED,
            payload: {
              channel,
              message
            }
          });
        }
      }));
      subscriber.set(topics.PUBSUB_TOPICS.DELETE_MESSAGE, pubSub.subscribe(topics.PUBSUB_TOPICS.DELETE_MESSAGE, msg => {
        const {
          channel,
          messageId
        } = msg;
        if ((currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.url) === (channel === null || channel === void 0 ? void 0 : channel.url)) {
          threadDispatcher({
            type: ThreadContextActionTypes.ON_MESSAGE_DELETED,
            payload: {
              messageId
            }
          });
        }
      }));
    };
    const subscriber = pubSubHandler();
    return () => {
      subscriber === null || subscriber === void 0 ? void 0 : subscriber.forEach(s => {
        try {
          s === null || s === void 0 ? void 0 : s.remove();
        } catch (_unused) {
          //
        }
      });
    };
  }, [sdkInit, currentChannel]);
}

function useHandleChannelEvents(_ref, _ref2) {
  let {
    sdk,
    currentChannel
  } = _ref;
  let {
    logger,
    threadDispatcher
  } = _ref2;
  React.useEffect(() => {
    var _sdk$groupChannel;
    const handlerId = uuid.uuidv4();
    // validation check
    if (sdk !== null && sdk !== void 0 && (_sdk$groupChannel = sdk.groupChannel) !== null && _sdk$groupChannel !== void 0 && _sdk$groupChannel.addGroupChannelHandler && currentChannel) {
      var _sdk$groupChannel$add, _sdk$groupChannel2;
      const channelHandlerParams = {
        // message status change
        onMessageReceived(channel, message) {
          logger.info('Thread | useHandleChannelEvents: onMessageReceived', {
            channel,
            message
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_MESSAGE_RECEIVED,
            payload: {
              channel,
              message
            }
          });
        },
        onMessageUpdated(channel, message) {
          logger.info('Thread | useHandleChannelEvents: onMessageUpdated', {
            channel,
            message
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_MESSAGE_UPDATED,
            payload: {
              channel,
              message
            }
          });
        },
        onMessageDeleted(channel, messageId) {
          logger.info('Thread | useHandleChannelEvents: onMessageDeleted', {
            channel,
            messageId
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_MESSAGE_DELETED,
            payload: {
              channel,
              messageId
            }
          });
        },
        onReactionUpdated(channel, reactionEvent) {
          logger.info('Thread | useHandleChannelEvents: onReactionUpdated', {
            channel,
            reactionEvent
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_REACTION_UPDATED,
            payload: {
              channel,
              reactionEvent
            }
          });
        },
        // user status change
        onUserMuted(channel, user) {
          logger.info('Thread | useHandleChannelEvents: onUserMuted', {
            channel,
            user
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_USER_MUTED,
            payload: {
              channel,
              user
            }
          });
        },
        onUserUnmuted(channel, user) {
          logger.info('Thread | useHandleChannelEvents: onUserUnmuted', {
            channel,
            user
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_USER_UNMUTED,
            payload: {
              channel,
              user
            }
          });
        },
        onUserBanned(channel, user) {
          logger.info('Thread | useHandleChannelEvents: onUserBanned', {
            channel,
            user
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_USER_BANNED,
            payload: {
              channel,
              user
            }
          });
        },
        onUserUnbanned(channel, user) {
          logger.info('Thread | useHandleChannelEvents: onUserUnbanned', {
            channel,
            user
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_USER_UNBANNED,
            payload: {
              channel,
              user
            }
          });
        },
        onUserLeft(channel, user) {
          logger.info('Thread | useHandleChannelEvents: onUserLeft', {
            channel,
            user
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_USER_LEFT,
            payload: {
              channel,
              user
            }
          });
        },
        // channel status change
        onChannelFrozen(channel) {
          logger.info('Thread | useHandleChannelEvents: onChannelFrozen', {
            channel
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_CHANNEL_FROZEN,
            payload: {
              channel
            }
          });
        },
        onChannelUnfrozen(channel) {
          logger.info('Thread | useHandleChannelEvents: onChannelUnfrozen', {
            channel
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_CHANNEL_UNFROZEN,
            payload: {
              channel
            }
          });
        },
        onOperatorUpdated(channel, users) {
          logger.info('Thread | useHandleChannelEvents: onOperatorUpdated', {
            channel,
            users
          });
          threadDispatcher({
            type: ThreadContextActionTypes.ON_OPERATOR_UPDATED,
            payload: {
              channel,
              users
            }
          });
        }
      };
      const channelHandler = new groupChannel.GroupChannelHandler(channelHandlerParams);
      (_sdk$groupChannel$add = (_sdk$groupChannel2 = sdk.groupChannel).addGroupChannelHandler) === null || _sdk$groupChannel$add === void 0 ? void 0 : _sdk$groupChannel$add.call(_sdk$groupChannel2, handlerId, channelHandler);
      logger.info('Thread | useHandleChannelEvents: Added channelHandler in Thread', {
        handlerId,
        channelHandler
      });
    }
    return () => {
      var _sdk$groupChannel3;
      // validation check
      if (handlerId && sdk !== null && sdk !== void 0 && (_sdk$groupChannel3 = sdk.groupChannel) !== null && _sdk$groupChannel3 !== void 0 && _sdk$groupChannel3.removeGroupChannelHandler) {
        var _sdk$groupChannel$rem, _sdk$groupChannel4;
        (_sdk$groupChannel$rem = (_sdk$groupChannel4 = sdk.groupChannel).removeGroupChannelHandler) === null || _sdk$groupChannel$rem === void 0 ? void 0 : _sdk$groupChannel$rem.call(_sdk$groupChannel4, handlerId);
        logger.info('Thread | useHandleChannelEvents: Removed channelHandler in Thread.', handlerId);
      }
    };
  }, [sdk === null || sdk === void 0 ? void 0 : sdk.groupChannel, currentChannel]);
}

function useSendFileMessageCallback(_ref, _ref2) {
  let {
    currentChannel
  } = _ref;
  let {
    logger,
    pubSub,
    threadDispatcher
  } = _ref2;
  const sendMessage = React.useCallback((file, quoteMessage) => {
    const createParamsDefault = () => {
      const params = {};
      params.file = file;
      if (quoteMessage) {
        params.isReplyToChannel = true;
        params.parentMessageId = quoteMessage.messageId;
      }
      return params;
    };
    const params = createParamsDefault();
    logger.info('Thread | useSendFileMessageCallback: Sending file message start.', params);
    currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.sendFileMessage(params).onPending(pendingMessage => {
      threadDispatcher({
        type: ThreadContextActionTypes.SEND_MESSAGE_START,
        payload: {
          /* pubSub is used instead of messagesDispatcher
          to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
          message: _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, pendingMessage), {}, {
            url: URL.createObjectURL(file),
            // pending thumbnail message seems to be failed
            requestState: 'pending'
          })
        }
      });
      setTimeout(() => scrollIntoLast(), 1000);
    }).onFailed((error, message) => {
      message.localUrl = URL.createObjectURL(file);
      message.file = file;
      logger.info('Thread | useSendFileMessageCallback: Sending file message failed.', {
        message,
        error
      });
      threadDispatcher({
        type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
        payload: {
          message,
          error
        }
      });
    }).onSucceeded(message => {
      logger.info('Thread | useSendFileMessageCallback: Sending file message succeeded.', message);
      pubSub.publish(topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, {
        channel: currentChannel,
        message: message
      });
    });
  }, [currentChannel]);
  return sendMessage;
}

function useUpdateMessageCallback(_ref, _ref2) {
  let {
    currentChannel,
    isMentionEnabled
  } = _ref;
  let {
    logger,
    pubSub,
    threadDispatcher
  } = _ref2;
  return React.useCallback(props => {
    var _currentChannel$updat;
    const {
      messageId,
      message,
      mentionedUsers,
      mentionTemplate
    } = props;
    const createParamsDefault = () => {
      const params = {};
      params.message = message;
      if (isMentionEnabled && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        params.mentionedUsers = mentionedUsers;
      }
      if (isMentionEnabled && mentionTemplate) {
        params.mentionedMessageTemplate = mentionTemplate;
      } else {
        params.mentionedMessageTemplate = message;
      }
      return params;
    };
    const params = createParamsDefault();
    logger.info('Thread | useUpdateMessageCallback: Message update start.', params);
    currentChannel === null || currentChannel === void 0 ? void 0 : (_currentChannel$updat = currentChannel.updateUserMessage) === null || _currentChannel$updat === void 0 ? void 0 : _currentChannel$updat.call(currentChannel, messageId, params).then(message => {
      logger.info('Thread | useUpdateMessageCallback: Message update succeeded.', message);
      threadDispatcher({
        type: ThreadContextActionTypes.ON_MESSAGE_UPDATED,
        payload: {
          channel: currentChannel,
          message: message
        }
      });
      pubSub.publish(topics.PUBSUB_TOPICS.UPDATE_USER_MESSAGE, {
        fromSelector: true,
        channel: currentChannel,
        message: message
      });
    });
  }, [currentChannel, isMentionEnabled]);
}

function useDeleteMessageCallback(_ref, _ref2) {
  let {
    currentChannel,
    threadDispatcher
  } = _ref;
  let {
    logger
  } = _ref2;
  return React.useCallback(message => {
    logger.info('Thread | useDeleteMessageCallback: Deleting message.', message);
    const {
      sendingStatus
    } = message;
    return new Promise((resolve, reject) => {
      var _currentChannel$delet;
      logger.info('Thread | useDeleteMessageCallback: Deleting message requestState:', sendingStatus);
      // Message is only on local
      if (sendingStatus === 'failed' || sendingStatus === 'pending') {
        logger.info('Thread | useDeleteMessageCallback: Deleted message from local:', message);
        threadDispatcher({
          type: ThreadContextActionTypes.ON_MESSAGE_DELETED_BY_REQ_ID,
          payload: message.reqId
        });
        resolve(message);
      }
      logger.info('Thread | useDeleteMessageCallback: Deleting message from remote:', sendingStatus);
      currentChannel === null || currentChannel === void 0 ? void 0 : (_currentChannel$delet = currentChannel.deleteMessage) === null || _currentChannel$delet === void 0 ? void 0 : _currentChannel$delet.call(currentChannel, message).then(() => {
        logger.info('Thread | useDeleteMessageCallback: Deleting message success!', message);
        threadDispatcher({
          type: ThreadContextActionTypes.ON_MESSAGE_DELETED,
          payload: {
            message,
            channel: currentChannel
          }
        });
        resolve(message);
      }).catch(err => {
        logger.warning('Thread | useDeleteMessageCallback: Deleting message failed!', err);
        reject(err);
      });
    });
  }, [currentChannel]);
}

function useGetPrevThreadsCallback(_ref, _ref2) {
  let {
    hasMorePrev,
    parentMessage,
    threadListState,
    oldestMessageTimeStamp,
    isReactionEnabled
  } = _ref;
  let {
    logger,
    threadDispatcher
  } = _ref2;
  return React.useCallback(callback => {
    // validation check
    if (threadListState === Thread_context_types.ThreadListStateTypes.INITIALIZED && parentMessage !== null && parentMessage !== void 0 && parentMessage.getThreadedMessagesByTimestamp && oldestMessageTimeStamp !== 0) {
      var _parentMessage$getThr;
      threadDispatcher({
        type: ThreadContextActionTypes.GET_PREV_MESSAGES_START,
        payload: null
      });
      (_parentMessage$getThr = parentMessage.getThreadedMessagesByTimestamp) === null || _parentMessage$getThr === void 0 ? void 0 : _parentMessage$getThr.call(parentMessage, oldestMessageTimeStamp, {
        prevResultSize: PREV_THREADS_FETCH_SIZE,
        nextResultSize: 0,
        includeReactions: isReactionEnabled,
        includeMetaArray: true
      }).then(_ref3 => {
        let {
          parentMessage,
          threadedMessages
        } = _ref3;
        logger.info('Thread | useGetPrevThreadsCallback: Fetch prev threads succeeded.', {
          parentMessage,
          threadedMessages
        });
        threadDispatcher({
          type: ThreadContextActionTypes.GET_PREV_MESSAGES_SUCESS,
          payload: {
            parentMessage,
            threadedMessages
          }
        });
        callback(threadedMessages);
      }).catch(error => {
        logger.info('Thread | useGetPrevThreadsCallback: Fetch prev threads failed.', error);
        threadDispatcher({
          type: ThreadContextActionTypes.GET_PREV_MESSAGES_FAILURE,
          payload: error
        });
      });
    }
  }, [hasMorePrev, parentMessage, threadListState, oldestMessageTimeStamp]);
}

function useGetNextThreadsCallback(_ref, _ref2) {
  let {
    hasMoreNext,
    parentMessage,
    threadListState,
    latestMessageTimeStamp,
    isReactionEnabled
  } = _ref;
  let {
    logger,
    threadDispatcher
  } = _ref2;
  return React.useCallback(callback => {
    // validation check
    if (threadListState === Thread_context_types.ThreadListStateTypes.INITIALIZED && parentMessage !== null && parentMessage !== void 0 && parentMessage.getThreadedMessagesByTimestamp && latestMessageTimeStamp !== 0) {
      var _parentMessage$getThr;
      threadDispatcher({
        type: ThreadContextActionTypes.GET_NEXT_MESSAGES_START,
        payload: null
      });
      (_parentMessage$getThr = parentMessage.getThreadedMessagesByTimestamp) === null || _parentMessage$getThr === void 0 ? void 0 : _parentMessage$getThr.call(parentMessage, latestMessageTimeStamp, {
        prevResultSize: 0,
        nextResultSize: NEXT_THREADS_FETCH_SIZE,
        includeReactions: isReactionEnabled,
        includeMetaArray: true
      }).then(_ref3 => {
        let {
          parentMessage,
          threadedMessages
        } = _ref3;
        logger.info('Thread | useGetNextThreadsCallback: Fetch next threads succeeded.', {
          parentMessage,
          threadedMessages
        });
        threadDispatcher({
          type: ThreadContextActionTypes.GET_NEXT_MESSAGES_SUCESS,
          payload: {
            parentMessage,
            threadedMessages
          }
        });
        callback(threadedMessages);
      }).catch(error => {
        logger.info('Thread | useGetNextThreadsCallback: Fetch next threads failed.', error);
        threadDispatcher({
          type: ThreadContextActionTypes.GET_NEXT_MESSAGES_FAILURE,
          payload: error
        });
      });
    }
  }, [hasMoreNext, parentMessage, threadListState, latestMessageTimeStamp]);
}

function useToggleReactionCallback(_ref, _ref2) {
  let {
    currentChannel
  } = _ref;
  let {
    logger
  } = _ref2;
  return React.useCallback((message, key, isReacted) => {
    var _currentChannel$addRe;
    if (isReacted) {
      var _currentChannel$delet;
      currentChannel === null || currentChannel === void 0 ? void 0 : (_currentChannel$delet = currentChannel.deleteReaction) === null || _currentChannel$delet === void 0 ? void 0 : _currentChannel$delet.call(currentChannel, message, key).then(res => {
        logger.info('Thread | useToggleReactionsCallback: Delete reaction succeeded.', res);
      }).catch(err => {
        logger.warning('Thread | useToggleReactionsCallback: Delete reaction failed.', err);
      });
      return;
    }
    currentChannel === null || currentChannel === void 0 ? void 0 : (_currentChannel$addRe = currentChannel.addReaction) === null || _currentChannel$addRe === void 0 ? void 0 : _currentChannel$addRe.call(currentChannel, message, key).then(res => {
      logger.info('Thread | useToggleReactionsCallback: Add reaction succeeded.', res);
    }).catch(err => {
      logger.warning('Thread | useToggleReactionsCallback: Add reaction failed.', err);
    });
  }, [currentChannel]);
}

function useSendUserMessageCallback(_ref, _ref2) {
  let {
    isMentionEnabled,
    currentChannel
  } = _ref;
  let {
    logger,
    pubSub,
    threadDispatcher
  } = _ref2;
  const sendMessage = React.useCallback(props => {
    const {
      message,
      quoteMessage = null,
      mentionTemplate,
      mentionedUsers
    } = props;
    const createDefaultParams = () => {
      const params = {};
      params.message = message;
      if (isMentionEnabled && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        params.mentionedUsers = mentionedUsers;
      }
      if (isMentionEnabled && mentionTemplate && (mentionedUsers === null || mentionedUsers === void 0 ? void 0 : mentionedUsers.length) > 0) {
        params.mentionedMessageTemplate = mentionTemplate;
      }
      if (quoteMessage) {
        params.isReplyToChannel = true;
        params.parentMessageId = quoteMessage.messageId;
      }
      return params;
    };
    const params = createDefaultParams();
    logger.info('Thread | useSendUserMessageCallback: Sending user message start.', params);
    if (currentChannel !== null && currentChannel !== void 0 && currentChannel.sendUserMessage) {
      currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.sendUserMessage(params).onPending(pendingMessage => {
        threadDispatcher({
          type: ThreadContextActionTypes.SEND_MESSAGE_START,
          payload: {
            message: pendingMessage
          }
        });
      }).onFailed((error, message) => {
        logger.info('Thread | useSendUserMessageCallback: Sending user message failed.', {
          message,
          error
        });
        threadDispatcher({
          type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
          payload: {
            error,
            message
          }
        });
      }).onSucceeded(message => {
        logger.info('Thread | useSendUserMessageCallback: Sending user message succeeded.', message);
        threadDispatcher({
          type: ThreadContextActionTypes.SEND_MESSAGE_SUCESS,
          payload: {
            message
          }
        });
        // because Thread doesn't subscribe SEND_USER_MESSAGE
        pubSub.publish(topics.PUBSUB_TOPICS.SEND_USER_MESSAGE, {
          channel: currentChannel,
          message: message
        });
      });
    }
  }, [isMentionEnabled, currentChannel]);
  return sendMessage;
}

function useResendMessageCallback(_ref, _ref2) {
  let {
    currentChannel
  } = _ref;
  let {
    logger,
    pubSub,
    threadDispatcher
  } = _ref2;
  return React.useCallback(failedMessage => {
    if (failedMessage !== null && failedMessage !== void 0 && failedMessage.isResendable) {
      var _failedMessage$isUser, _failedMessage$isFile;
      failedMessage.sendingStatus = message.SendingStatus.PENDING;
      logger.info('Thread | useResendMessageCallback: Resending failedMessage start.', failedMessage);
      threadDispatcher({
        type: ThreadContextActionTypes.RESEND_MESSAGE_START,
        payload: failedMessage
      });
      if (failedMessage !== null && failedMessage !== void 0 && (_failedMessage$isUser = failedMessage.isUserMessage) !== null && _failedMessage$isUser !== void 0 && _failedMessage$isUser.call(failedMessage) || (failedMessage === null || failedMessage === void 0 ? void 0 : failedMessage.messageType) === message.MessageType.USER) {
        currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.resendUserMessage(failedMessage).then(message => {
          logger.info('Thread | useResendMessageCallback: Resending failedMessage succeeded.', message);
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_SUCESS,
            payload: {
              message
            }
          });
          pubSub.publish(topics.PUBSUB_TOPICS.SEND_USER_MESSAGE, {
            channel: currentChannel,
            message: message
          });
        }).catch(error => {
          logger.warning('Thread | useResendMessageCallback: Resending failedMessage failed.', error);
          failedMessage.sendingStatus = message.SendingStatus.FAILED;
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
            payload: {
              message: failedMessage
            }
          });
        });
      } else if (failedMessage !== null && failedMessage !== void 0 && (_failedMessage$isFile = failedMessage.isFileMessage) !== null && _failedMessage$isFile !== void 0 && _failedMessage$isFile.call(failedMessage) || (failedMessage === null || failedMessage === void 0 ? void 0 : failedMessage.messageType) === message.MessageType.FILE) {
        var _currentChannel$resen;
        currentChannel === null || currentChannel === void 0 ? void 0 : (_currentChannel$resen = currentChannel.resendFileMessage) === null || _currentChannel$resen === void 0 ? void 0 : _currentChannel$resen.call(currentChannel, failedMessage).then(message => {
          logger.info('Thread | useResendMessageCallback: Resending failedMessage succeeded.', message);
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_SUCESS,
            payload: {
              message
            }
          });
        }).catch(error => {
          logger.warning('Thread | useResendMessageCallback: Resending failedMessage failed.', error);
          failedMessage.sendingStatus = message.SendingStatus.FAILED;
          threadDispatcher({
            type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
            payload: {
              message: failedMessage
            }
          });
          pubSub.publish(topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, {
            channel: currentChannel,
            message: failedMessage
          });
        });
      } else {
        logger.warning('Thread | useResendMessageCallback: Message is not resendable.', failedMessage);
        failedMessage.sendingStatus = message.SendingStatus.FAILED;
        threadDispatcher({
          type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
          payload: {
            message: failedMessage
          }
        });
      }
    }
  }, [currentChannel]);
}

const useSendVoiceMessageCallback = (_ref, _ref2) => {
  let {
    currentChannel,
    onBeforeSendVoiceMessage
  } = _ref;
  let {
    logger,
    pubSub,
    threadDispatcher
  } = _ref2;
  const sendMessage = React.useCallback((file, duration, quoteMessage) => {
    const messageParams = onBeforeSendVoiceMessage && typeof onBeforeSendVoiceMessage === 'function' ? onBeforeSendVoiceMessage(file, quoteMessage) : {
      file,
      fileName: consts.VOICE_MESSAGE_FILE_NAME,
      mimeType: consts.VOICE_MESSAGE_MIME_TYPE,
      metaArrays: [new message.MessageMetaArray({
        key: consts.META_ARRAY_VOICE_DURATION_KEY,
        value: [`${duration}`]
      }), new message.MessageMetaArray({
        key: consts.META_ARRAY_MESSAGE_TYPE_KEY,
        value: [consts.META_ARRAY_MESSAGE_TYPE_VALUE__VOICE]
      })]
    };
    if (quoteMessage) {
      messageParams.isReplyToChannel = true;
      messageParams.parentMessageId = quoteMessage.messageId;
    }
    logger.info('Thread | useSendVoiceMessageCallback:  Start sending voice message', messageParams);
    currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.sendFileMessage(messageParams).onPending(pendingMessage => {
      threadDispatcher({
        type: ThreadContextActionTypes.SEND_MESSAGE_START,
        payload: {
          /* pubSub is used instead of messagesDispatcher
          to avoid redundantly calling `messageActionTypes.SEND_MESSAGEGE_START` */
          message: _rollupPluginBabelHelpers._objectSpread2(_rollupPluginBabelHelpers._objectSpread2({}, pendingMessage), {}, {
            url: URL.createObjectURL(file),
            // pending thumbnail message seems to be failed
            requestState: 'pending'
          })
        }
      });
      setTimeout(() => scrollIntoLast(), 1000);
    }).onFailed((error, message) => {
      message.localUrl = URL.createObjectURL(file);
      message.file = file;
      logger.info('Thread | useSendVoiceMessageCallback: Sending voice message failed.', {
        message,
        error
      });
      threadDispatcher({
        type: ThreadContextActionTypes.SEND_MESSAGE_FAILURE,
        payload: {
          message,
          error
        }
      });
    }).onSucceeded(message => {
      logger.info('Thread | useSendVoiceMessageCallback: Sending voice message succeeded.', message);
      pubSub.publish(topics.PUBSUB_TOPICS.SEND_FILE_MESSAGE, {
        channel: currentChannel,
        message: message
      });
    });
  }, [currentChannel, onBeforeSendVoiceMessage]);
  return sendMessage;
};

const ThreadContext = /*#__PURE__*/React__default["default"].createContext(null);
const ThreadProvider = props => {
  var _allThreadMessages$, _allThreadMessages;
  const {
    children,
    channelUrl,
    onHeaderActionClick,
    onMoveToParentMessage,
    onBeforeSendVoiceMessage,
    // User Profile
    disableUserProfile,
    renderUserProfile
  } = props;
  const propsMessage = props === null || props === void 0 ? void 0 : props.message;
  const propsParentMessage = getParentMessageFrom(propsMessage);
  // Context from SendbirdProvider
  const globalStore = useSendbirdStateContext();
  const {
    stores,
    config
  } = globalStore;
  // // stores
  const {
    sdkStore,
    userStore
  } = stores;
  const {
    sdk
  } = sdkStore;
  const {
    user
  } = userStore;
  const sdkInit = sdkStore === null || sdkStore === void 0 ? void 0 : sdkStore.initialized;
  // // config
  const {
    logger,
    pubSub,
    replyType,
    isMentionEnabled,
    isReactionEnabled,
    onUserProfileMessage
  } = config;

  // dux of Thread
  const [threadStore, threadDispatcher] = React.useReducer(reducer, initialState);
  const {
    currentChannel,
    allThreadMessages,
    parentMessage,
    channelState,
    threadListState,
    parentMessageState,
    hasMorePrev,
    hasMoreNext,
    emojiContainer,
    isMuted,
    isChannelFrozen,
    currentUserId
  } = threadStore;

  // Initialization
  React.useEffect(() => {
    threadDispatcher({
      type: ThreadContextActionTypes.INIT_USER_ID,
      payload: user === null || user === void 0 ? void 0 : user.userId
    });
  }, [user]);
  useGetChannel({
    channelUrl,
    sdkInit,
    message: propsMessage
  }, {
    sdk,
    logger,
    threadDispatcher
  });
  useGetParentMessage({
    channelUrl,
    sdkInit,
    parentMessage: propsParentMessage
  }, {
    sdk,
    logger,
    threadDispatcher
  });
  useGetThreadList({
    sdkInit,
    parentMessage,
    isReactionEnabled,
    anchorMessage: (propsMessage === null || propsMessage === void 0 ? void 0 : propsMessage.messageId) !== (propsParentMessage === null || propsParentMessage === void 0 ? void 0 : propsParentMessage.messageId) ? propsMessage : null
    // anchorMessage should be null when parentMessage doesn't exist
  }, {
    logger,
    threadDispatcher
  });
  useGetAllEmoji({
    sdk
  }, {
    logger,
    threadDispatcher
  });
  // Handle channel events
  useHandleChannelEvents({
    sdk,
    currentChannel
  }, {
    logger,
    threadDispatcher
  });
  useHandlePubsubEvents({
    sdkInit,
    currentChannel,
    parentMessage
  }, {
    logger,
    pubSub,
    threadDispatcher
  });

  // callbacks
  const fetchPrevThreads = useGetPrevThreadsCallback({
    hasMorePrev,
    parentMessage,
    threadListState,
    isReactionEnabled,
    oldestMessageTimeStamp: ((_allThreadMessages$ = allThreadMessages[0]) === null || _allThreadMessages$ === void 0 ? void 0 : _allThreadMessages$.createdAt) || 0
  }, {
    logger,
    threadDispatcher
  });
  const fetchNextThreads = useGetNextThreadsCallback({
    hasMoreNext,
    parentMessage,
    threadListState,
    isReactionEnabled,
    latestMessageTimeStamp: ((_allThreadMessages = allThreadMessages[allThreadMessages.length - 1]) === null || _allThreadMessages === void 0 ? void 0 : _allThreadMessages.createdAt) || 0
  }, {
    logger,
    threadDispatcher
  });
  const toggleReaction = useToggleReactionCallback({
    currentChannel
  }, {
    logger
  });
  const sendMessage = useSendUserMessageCallback({
    isMentionEnabled,
    currentChannel
  }, {
    logger,
    pubSub,
    threadDispatcher
  });
  const sendFileMessage = useSendFileMessageCallback({
    currentChannel
  }, {
    logger,
    pubSub,
    threadDispatcher
  });
  const sendVoiceMessage = useSendVoiceMessageCallback({
    currentChannel,
    onBeforeSendVoiceMessage
  }, {
    logger,
    pubSub,
    threadDispatcher
  });
  const resendMessage = useResendMessageCallback({
    currentChannel
  }, {
    logger,
    pubSub,
    threadDispatcher
  });
  const updateMessage = useUpdateMessageCallback({
    currentChannel,
    isMentionEnabled
  }, {
    logger,
    pubSub,
    threadDispatcher
  });
  const deleteMessage = useDeleteMessageCallback({
    currentChannel,
    threadDispatcher
  }, {
    logger
  });

  // memo
  const nicknamesMap = React.useMemo(() => replyType && currentChannel ? getNicknamesMapFromMembers(currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.members) : new Map(), [currentChannel === null || currentChannel === void 0 ? void 0 : currentChannel.members]);
  return /*#__PURE__*/React__default["default"].createElement(ThreadContext.Provider, {
    value: {
      // ThreadProviderProps
      channelUrl,
      message: propsMessage,
      onHeaderActionClick,
      onMoveToParentMessage,
      // ThreadContextInitialState
      currentChannel,
      allThreadMessages,
      parentMessage,
      channelState,
      threadListState,
      parentMessageState,
      hasMorePrev,
      hasMoreNext,
      emojiContainer,
      // hooks
      fetchPrevThreads,
      fetchNextThreads,
      toggleReaction,
      sendMessage,
      sendFileMessage,
      sendVoiceMessage,
      resendMessage,
      updateMessage,
      deleteMessage,
      // context
      nicknamesMap,
      isMuted,
      isChannelFrozen,
      currentUserId
    }
  }, /*#__PURE__*/React__default["default"].createElement(UserProfileContext.UserProfileProvider, {
    disableUserProfile: disableUserProfile !== null && disableUserProfile !== void 0 ? disableUserProfile : config.disableUserProfile,
    renderUserProfile: renderUserProfile,
    onUserProfileMessage: onUserProfileMessage
  }, children));
};
const useThreadContext = () => React__default["default"].useContext(ThreadContext);

exports.ThreadProvider = ThreadProvider;
exports.compareMessagesForGrouping = compareMessagesForGrouping;
exports.isAboutSame = isAboutSame;
exports.useThreadContext = useThreadContext;
//# sourceMappingURL=ThreadProvider-593ade0c.js.map
