"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Message = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _reactRedux = require("react-redux");
var _Avatar = require("./Avatar");
var _MessageInteractions = _interopRequireDefault(require("./MessageInteractions"));
var _BottomReplyContainer = require("./BottomReplyContainer");
var _MessageReply = require("./MessageReply");
var _DeletedMessage = require("./DeletedMessage");
var _chatSettingsSlice = require("../../roomStore/chatSettingsSlice");
var _MODAL_TYPES = require("../../helpers/constants/MODAL_TYPES");
var _roomsSlice = require("../../roomStore/roomsSlice");
var _native = _interopRequireDefault(require("styled-components/native"));
var _MediaMessage = _interopRequireDefault(require("../MainComponents/MediaMessage"));
var _MessageTranslations = _interopRequireDefault(require("./MessageTranslations"));
var _useChatSettingState = require("../../hooks/useChatSettingState");
var _parseMessageBody = require("../../helpers/parseMessageBody");
var _useMessageHeapState = require("../../hooks/useMessageHeapState");
var _icons = require("../../assets/icons");
var _xmppProvider = require("../../context/xmppProvider");
var _useSendMessage = require("../../hooks/useSendMessage");
var _MessageReaction = require("./MessageReaction");
var _StyledComponents = require("../styled/StyledComponents");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const CustomMessageContainer = _native.default.View`
  flex-direction: row;
  padding: 10px;
  align-items: flex-end;
  justify-content: ${({
  isUser
}) => isUser ? 'flex-end' : 'flex-start'};
  margin-bottom: ${props => props.reply ? '20px' : '0px'};
`;
const CustomMessageBubble = _native.default.View`
  position: relative;
  max-width: 85%;
  min-width: ${({
  isMedia
}) => isMedia ? '0' : '30%'};
  align-items: ${({
  isMedia,
  isUser
}) => isMedia ? isUser ? 'flex-end' : 'flex-start' : 'stretch'};
  padding: ${({
  isMedia
}) => isMedia ? '0' : '10'}px;
  padding-bottom: ${({
  isMedia
}) => isMedia ? '6' : '10'}px;
  margin-right: ${({
  isUser
}) => isUser ? '0' : '10px'};
  margin-left: ${({
  isUser
}) => isUser ? '10px' : '0'};
  border-radius: 10px;
  overflow: hidden;
  border-bottom-left-radius: ${({
  isUser
}) => isUser ? '10' : '0'}px;
  border-bottom-right-radius: ${({
  isUser
}) => isUser ? '0' : '10'}px;
  background-color: ${({
  isUser,
  deleted,
  backgroundMessageUser,
  backgroundMessage
}) => deleted ? '#f5f5f5' : isUser ? backgroundMessageUser || '#d1e7ff' : backgroundMessage || '#fff'};
`;
const CustomMessageText = _native.default.Text`
  font-size: 16px;
  color: ${({
  color,
  colorUser,
  isUser
}) => isUser ? colorUser || '#333' : color || '#333'};
`;
const CustomMessagePhoto = _native.default.Image`
  width: 40px;
  height: 40px;
  border-radius: 20px;
`;
const CustomMessagePhotoContainer = _native.default.TouchableOpacity`
  margin-right: 10px;
`;
const CustomUserName = _native.default.Text`
  font-size: 14px;
  font-weight: 500;
  padding-bottom: 8px;
  padding-left: ${({
  media
}) => media ? '16px' : 0};
  padding-top: ${({
  media
}) => media ? '8px' : 0};
  color: ${({
  color
}) => color || '#333'};
`;
const CustomMessageTimestamp = _native.default.Text`
  font-size: 12px;
  color: #999;
  color: ${({
  isUser,
  color,
  colorUser
}) => isUser ? colorUser || '#999' : color || '#999'};
  margin-top: 5px;
  align-self: flex-end;
`;
const CustomTimestampRow = _native.default.View`
  flex-direction: row;
  align-items: center;
  align-self: flex-end;
  margin-top: 4;
  gap: 4;
  padding-right: ${({
  media
}) => media ? '10px' : 0};
`;
const Message = ({
  message,
  isUser,
  isReply
}) => {
  const dispatch = (0, _reactRedux.useDispatch)();
  const {
    client
  } = (0, _xmppProvider.useXmppClient)();
  const {
    config,
    langSource,
    user
  } = (0, _useChatSettingState.useChatSettingState)();
  const {
    idSet,
    failedIdSet
  } = (0, _useMessageHeapState.useMessageHeapState)();
  const {
    retryMessage
  } = (0, _useSendMessage.useSendMessage)();
  const [isPressed, setIsPressed] = (0, _react.useState)(false);
  if (__DEV__ && message.id && !globalThis.__loggedMsg?.[message.id]) {
    (globalThis.__loggedMsg ||= {})[message.id] = true;
  }
  const [contextMenuPosition, setContextMenuPosition] = (0, _react.useState)(null);
  const timerRef = (0, _react.useRef)(null);
  const messageRef = (0, _react.useRef)(null);
  const bubbleRef = (0, _react.useRef)(null);
  const handleUserAvatarClick = user => {
    dispatch((0, _chatSettingsSlice.setActiveModal)(_MODAL_TYPES.MODAL_TYPES.PROFILE));
    dispatch((0, _chatSettingsSlice.setSelectedUser)(user));
  };
  const handleReplyMessage = () => {
    dispatch((0, _roomsSlice.setEditAction)({
      isEdit: false
    }));
    if (!isReply && message.mainMessage) {
      const messageCore = JSON.parse(message.mainMessage);
      dispatch((0, _roomsSlice.setActiveMessage)({
        id: messageCore.id,
        chatJID: messageCore.roomJid
      }));
      return setIsPressed(false);
    }
    dispatch((0, _roomsSlice.setActiveMessage)({
      id: message.id,
      chatJID: message.roomJid
    }));
    return setIsPressed(false);
  };
  const handleDeleteMessage = () => {
    dispatch((0, _chatSettingsSlice.setDeleteModal)({
      isDeleteModal: true,
      roomJid: message.roomJid,
      messageId: message.id
    }));
    setIsPressed(false);
  };
  const handleEditMessage = () => {
    dispatch((0, _roomsSlice.setEditAction)({
      isEdit: true,
      roomJid: message.roomJid,
      messageId: message.id,
      text: message.body
    }));
    return setIsPressed(false);
  };

  // const handleLongPress = () => {
  //   setIsPressed(true);
  //   console.log("setIsPressed", isPressed);
  // };

  const handleReactionMessage = emoji => {
    if (!message.reaction) {
      return client?.sendMessageReactionStanza(message.id, message.roomJid, [emoji], `${user.firstName} ${user.lastName}`);
    }
    if (message.reaction && message.reaction[user.xmppUsername || ''] && message.reaction[user.xmppUsername || '']?.emoji.includes(emoji)) {
      const filterEmoji = message.reaction[user.xmppUsername || '']?.emoji.filter(reaction => reaction !== emoji);
      return client?.sendMessageReactionStanza(message.id, message.roomJid, filterEmoji, `${user.firstName} ${user.lastName}`);
    }
    client?.sendMessageReactionStanza(message.id, message.roomJid, [...(message.reaction[user.xmppUsername || '']?.emoji || []), emoji], `${user.firstName} ${user.lastName}`);
  };

  // Long-press → capture the bubble's on-screen bounding box. The actual
  // menu placement (above / below, clamped to the viewport) is done in
  // MessageInteractions, which measures the rendered menu height via
  // onLayout — more accurate than estimating it here, and it's what keeps
  // the menu adjacent to the message instead of floating far above (#13).
  const handleLongPress = () => {
    const target = bubbleRef.current ?? messageRef.current;
    if (target?.measureInWindow) {
      // Use measureInWindow — the SAME API the overlay host uses to find
      // its own window origin. Both are then in identical window
      // coordinates, so MessageInteractions' host-local conversion
      // (subtract origin) is exact. Mixing this with UIManager.measure
      // (pageX/pageY) drifted on Android (status-bar offset) and pushed the
      // "below" menu too far from the message.
      target.measureInWindow((x, y, width, height) => {
        setContextMenuPosition({
          left: x,
          right: x + width,
          top: y,
          bottom: y + height
        });
      });
    } else if (target) {
      const nodeHandle = (0, _reactNative.findNodeHandle)(target);
      if (nodeHandle) {
        _reactNative.UIManager.measure(nodeHandle, (_x, _y, width, height, pageX, pageY) => {
          setContextMenuPosition({
            left: pageX,
            right: pageX + width,
            top: pageY,
            bottom: pageY + height
          });
        });
      }
    }
    setIsPressed(true);
  };
  const messageText = config?.messageTextFilter?.enabled ? (0, _parseMessageBody.parseMessageBody)(config?.messageTextFilter.filterFunction(message.body)) : (0, _parseMessageBody.parseMessageBody)(message.body);
  const isFailed = failedIdSet.has(message.id);
  const isPending = !isFailed && (idSet.has(message.id) || message?.pending || false);
  const onRetryPress = () => {
    if (isFailed) {
      retryMessage(message.id);
    }
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
    children: [isPressed && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
      style: styles.overlay
    }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
      ref: messageRef,
      style: [styles.customMessageContainer, {
        justifyContent: isUser ? 'flex-end' : 'flex-start',
        marginBottom: !!message?.reply?.length || message?.reaction && !!Object.keys(message?.reaction)?.length ? 20 : 0
      }, isPressed ? {
        transform: [{
          scale: 1.05
        }],
        paddingRight: 16
      } : undefined
      // justify-content: ${({ isUser }) => (isUser ? "flex-end" : "flex-start")},
      // margin-bottom: ${(props) => !!props.reply && "20px"},
      ],
      children: [!isUser && /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomMessagePhotoContainer
      // `disableProfilesInteractions` gates every entry point to the
      // user-profile popup: this in-bubble avatar AND the chat-title
      // press in ChatHeader. When disabled we still render the avatar
      // visually but make it non-interactive (no press, no a11y
      // affordance) — consumers who want it gone entirely can return
      // null from a custom message component.
      , {
        onPress: config?.disableProfilesInteractions ? undefined : () => handleUserAvatarClick(message.user),
        disabled: !!config?.disableProfilesInteractions,
        accessible: !config?.disableProfilesInteractions,
        children: message.user?.profileImage ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomMessagePhoto, {
          source: {
            uri: message.user.profileImage
          }
        }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.Avatar, {
          username: message.user.name
        })
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable
      // The Pressable fills the row's content area, so the bubble
      // inside must be aligned to the sender's side — otherwise it
      // hugs the left and own media bubbles sit with a right-side
      // gap (text bubbles only looked right because they're narrow).
      // flex-end for own, flex-start for others.
      , {
        style: {
          flex: 1,
          alignItems: isUser ? 'flex-end' : 'flex-start'
        }
        // A plain tap anywhere on a message bubble dismisses the
        // keyboard. The FlatList's keyboardShouldPersistTaps="handled"
        // already dismisses taps on the empty GAPS between bubbles, but
        // the bubble Pressable itself is a touch responder, so taps that
        // landed on a message were "handled" and the keyboard stayed —
        // which is exactly the "closes only every other time" symptom
        // (hit a gap → close, hit a bubble → stay). Explicitly dismissing
        // here makes it reliable across the whole list. onPress does NOT
        // fire when onLongPress fires, so opening MessageInteractions via
        // long-press never triggers this dismiss.
        ,
        onPress: () => _reactNative.Keyboard.dismiss()
        // disableInteractions hides the long-press → context menu
        // (delete / edit / reply / react). Mirrors web's config gate.
        ,
        onLongPress: config?.disableInteractions ? undefined : handleLongPress,
        delayLongPress: 500,
        children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(CustomMessageBubble, {
          ref: bubbleRef,
          collapsable: false,
          isUser: isUser,
          deleted: message.isDeleted,
          isMedia: message?.isMediafile === 'true' && !message?.isDeleted,
          backgroundMessageUser: config?.messageColor?.backgroundMessageUser,
          backgroundMessage: config?.messageColor?.backgroundMessage,
          children: [!isUser && /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomUserName, {
            color: config?.colors?.primary,
            media: message?.isMediafile === 'true',
            children: message.user.name
          }), !isReply && message.mainMessage && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageReply.MessageReply, {
            handleReplyMessage: handleReplyMessage,
            isUser: isUser,
            text: JSON.parse(message.mainMessage).text,
            color: config?.colors?.primary
          }), message?.isMediafile === 'true' && !message?.isDeleted ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_MediaMessage.default, {
            mimeType: message.mimetype,
            messageText: message.locationPreview,
            location: message?.location,
            message: message,
            isUser: isUser
          }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
            children: message.isDeleted && message.id !== 'delimiter-new' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_DeletedMessage.DeletedMessage, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomMessageText, {
              isUser: isUser,
              colorUser: config?.messageColor?.colorUser,
              color: config?.messageColor?.color,
              children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
                children: messageText
              })
            })
          }), config?.enableTranslates && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageTranslations.default, {
            message: message,
            config: config,
            langSource: langSource
          }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(CustomTimestampRow, {
            media: message?.isMediafile === 'true',
            children: [!config?.disableSentLogic && isUser && isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              style: styles.timestampText,
              children: "sending..."
            }), !config?.disableSentLogic && isUser && isFailed && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              onPress: onRetryPress,
              style: styles.failedText,
              accessibilityRole: "button",
              accessibilityLabel: "Retry sending message",
              children: "! Failed \u2014 tap to retry"
            }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
              style: styles.timestampText,
              children: new Date(message.date).toLocaleTimeString([], {
                hour: '2-digit',
                minute: '2-digit'
              })
            }), !config?.disableSentLogic && isUser && !isPending && !isFailed && /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.DoubleTick, {})]
          }), message?.reply?.length && message?.reply?.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_BottomReplyContainer.BottomReplyContainer, {
            isUser: isUser,
            onClick: handleReplyMessage,
            reply: message?.reply
          }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_StyledComponents.MessageFooter, {
            isUser: isUser,
            children: message.reaction && !config?.disableReactions && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageReaction.MessageReaction, {
              reaction: message.reaction,
              changeReaction: handleReactionMessage,
              color: config?.colors?.primary || '#0052CD',
              userName: `${user.firstName} ${user.lastName}`
            })
          })]
        })
      })]
    }), !config?.disableInteractions && isPressed && /*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageInteractions.default, {
      position: contextMenuPosition,
      isReply: isReply,
      isUser: isUser,
      message: message,
      closeMenu: () => setIsPressed(false),
      handleReplyMessage: handleReplyMessage,
      handleDeleteMessage: handleDeleteMessage,
      handleEditMessage: handleEditMessage,
      handleReactionMessage: handleReactionMessage
    })]
  });
};
exports.Message = Message;
const styles = _reactNative.StyleSheet.create({
  customMessageContainer: {
    flexDirection: 'row',
    padding: 10,
    alignItems: 'flex-end',
    position: 'relative'
  },
  overlay: {
    ..._reactNative.StyleSheet.absoluteFillObject,
    position: 'absolute',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%'
    // backgroundColor: "rgba(0, 0, 0, 0.3)",
  },
  timestamp: {
    fontSize: 12,
    color: '#999',
    marginTop: 5,
    alignSelf: 'flex-end'
  },
  failedText: {
    color: '#E53935',
    fontWeight: '600',
    marginRight: 6
  },
  // Row keeps the time text and the DoubleTick SVG on the same line.
  // The time Text gets an explicit lineHeight equal to the 16px tick so
  // both occupy the same-height box; with alignItems center they line up
  // exactly. Without the lineHeight the Text's natural line box was
  // shorter than the icon, so the centred tick floated above the digits.
  timestampRow: {
    flexDirection: 'row',
    alignItems: 'center',
    alignSelf: 'flex-end',
    marginTop: 4,
    gap: 4
  },
  timestampText: {
    fontSize: 12,
    lineHeight: 16,
    color: '#999',
    includeFontPadding: false,
    textAlignVertical: 'center'
  }
});
//# sourceMappingURL=Message.js.map