"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ChatMessageBody = void 0;
var _react = _interopRequireWildcard(require("react"));
var _isEqual = _interopRequireDefault(require("lodash-es/isEqual"));
var _classnames = _interopRequireDefault(require("classnames"));
var _slate = require("slate");
var _slateReact = require("slate-react");
var _button = require("../button");
var _dropdown = require("../dropdown");
var _typeahead = require("../typeahead");
var _charactersCounter = require("./characters-counter");
var _hocs = require("./hocs");
var _constants = require("./constants");
var _renderers = require("./renderers");
var _utils = require("./utils");
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); }
function ChatMessageBodyBase({
  itemKey,
  textBoxAriaLabel,
  onChange,
  onSubmit,
  onMention,
  onBlur,
  readOnly,
  maxLength,
  getCharactersCounterString,
  mentions = [],
  actions,
  onActionBtnClick,
  editableContentClassName,
  mentionsPropmptText,
  autoFocus,
  value = _constants.DEFAULT_VALUE
}) {
  const anchorRef = (0, _react.useRef)(null);
  const [target, setTarget] = (0, _react.useState)();
  const [search, setSearch] = (0, _react.useState)('');
  const [showPropmt, setShowPrompt] = (0, _react.useState)(false);
  const [isMenuOpened, setIsMenuOpened] = (0, _react.useState)(false);
  const hasMentionsSupport = !!onMention;
  const editor = (0, _react.useMemo)(() => (0, _hocs.withMaxLength)(maxLength)((0, _hocs.withMentions)((0, _slateReact.withReact)((0, _slate.createEditor)()))), []);
  const isFocused = _slateReact.ReactEditor.isFocused(editor);
  const onKeyDown = (0, _react.useCallback)(event => {
    if (event.key === 'Enter' && target && mentions?.length) {
      event.preventDefault();
    }
    if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
      event.preventDefault();
      onSubmit({
        key: itemKey,
        value
      });
    }
  }, [mentions, target, value, itemKey, onSubmit]);
  const handleChange = (0, _react.useCallback)(val => {
    onChange({
      key: itemKey,
      value: val
    });
    const {
      selection
    } = editor;
    if (selection && _slate.Range.isCollapsed(selection)) {
      const [start] = _slate.Range.edges(selection);
      const wordBefore = _slate.Editor.before(editor, start, {
        unit: 'word'
      });
      const before = wordBefore && _slate.Editor.before(editor, wordBefore);
      const beforeRange = before && _slate.Editor.range(editor, before, start);
      const beforeText = beforeRange && _slate.Editor.string(editor, beforeRange);
      const beforeMatch = beforeText?.match(_constants.MENTION_PATTERN);
      const after = _slate.Editor.after(editor, start);
      const afterRange = _slate.Editor.range(editor, start, after);
      const afterText = _slate.Editor.string(editor, afterRange);
      const afterMatch = afterText.match(_constants.WHITE_SPACE_PATTERN);
      const [node] = _slate.Editor.node(editor, selection);
      if (beforeMatch && afterMatch) {
        anchorRef.current = _slateReact.ReactEditor.toDOMNode(editor, node);
        setTarget(beforeRange);
        setSearch(beforeMatch[1]);
        setIsMenuOpened(true);
        setShowPrompt(false);
        return;
      }
      if (node.text.endsWith('@') && !search) {
        anchorRef.current = _slateReact.ReactEditor.toDOMNode(editor, node);
        setIsMenuOpened(true);
        setShowPrompt(true);
        return;
      }
    }
    setTarget(null);
    setSearch('');
    setIsMenuOpened(false);
    setShowPrompt(false);
    anchorRef.current = null;
  }, [onChange, itemKey]);
  const handleSelect = (0, _react.useCallback)(({
    username,
    key
  }) => {
    _slate.Transforms.select(editor, target);
    (0, _renderers.insertMention)(editor, username, key);
    setTarget(null);
  }, [editor, target]);
  const closeMenu = (0, _react.useCallback)(() => setIsMenuOpened(false), []);
  const currLength = editor.children.length ? _slate.Editor.string(editor, []).length + (0, _utils.getMentionsCount)(editor.children) : 0;
  (0, _react.useEffect)(() => {
    if (autoFocus && !readOnly) {
      _slateReact.ReactEditor.focus(editor);
      _slate.Transforms.select(editor, _slate.Editor.end(editor, []));
    }
  }, [readOnly]);
  (0, _react.useEffect)(() => {
    onMention?.({
      value: search,
      key: itemKey
    });
  }, [search]);
  (0, _react.useEffect)(() => {
    if (!(0, _isEqual.default)(editor.children, value)) {
      (0, _utils.resetNodes)(editor, value);
    }
  }, [value, editor]);
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
    children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_slateReact.Slate, {
      editor: editor,
      initialValue: value,
      onChange: handleChange,
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        "test-id": `chat-item-body-editable-content-${itemKey}`,
        className: (0, _classnames.default)('chat-item-editable-content', editableContentClassName, {
          'read-only': readOnly
        }),
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_slateReact.Editable, {
          className: "slate-content-editable",
          readOnly: readOnly,
          onKeyDown: onKeyDown
          // @ts-expect-error: late types written in the way that disallow custom elements used in their examples
          ,
          renderElement: _renderers.renderElement,
          onBlur: onBlur,
          "aria-label": readOnly ? undefined : textBoxAriaLabel,
          onDOMBeforeInput: event => {
            // we have logic to prevent entering text longer than maxLength in hocs.ts
            // but there we prevent it only from updating slate inner state, html input still
            // adds entered text to the DOM input field causing buggy behavior: https://datarobot.atlassian.net/browse/TESTLIO-2963
            // preventing default from the onDOMBeforeInput won't add new character to the DOM input field.
            // we still want to leave logic in hocs.ts because it covers copy+paste case, as for some reason
            // under certain circumstances onDOMBeforeInput stops being triggering for copy+paste so having there is safer

            // we want to always allow deleting text
            if (!event.inputType.startsWith('delete')) {
              const existingMentionsCount = (0, _utils.getMentionsCount)(editor.children);
              if (!!event.data && _slate.Editor.string(editor, []).length + existingMentionsCount + (event?.data?.length ?? 0) > maxLength) {
                event.preventDefault();
              }
            }
          }
        })
      }), hasMentionsSupport && isFocused && /*#__PURE__*/(0, _jsxRuntime.jsx)(_dropdown.PopperDropdownWrapper, {
        closeDropdown: closeMenu,
        anchorRef: anchorRef.current,
        open: isMenuOpened,
        placement: _dropdown.DROPDOWN_PLACEMENT_TYPES.BOTTOM_START,
        contentClassName: "typeahead-dropdown-content",
        children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
          children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_typeahead.TypeaheadOptionList, {
            optionComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typeahead.ItemComponents.DefaultItem, {
              nameKey: _constants.MENTION_SEARCH_FIELD
            }),
            searchFields: _constants.MENTION_SEARCH_FIELDS,
            searchValue: search,
            closeDropdown: closeMenu,
            handleSelect: handleSelect,
            optionId: "key",
            optionLabel: _constants.MENTION_SEARCH_FIELD,
            options: mentions
          }), showPropmt && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
            className: "chat-mention-prompt",
            "test-id": "chat-mention-prompt",
            children: mentionsPropmptText
          })]
        })
      })]
    }), !readOnly && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_charactersCounter.CharactersCounter, {
        currLength: currLength,
        maxLength: maxLength,
        getCharactersCounterString: getCharactersCounterString
      }), !!actions?.length && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        className: "chat-item-actions",
        children: actions.map(({
          key,
          label,
          accentType,
          testId,
          isDisabled
        }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
          testId: testId,
          accentType: accentType,
          isDisabled: isDisabled,
          onClick: () => onActionBtnClick?.({
            itemKey,
            actionKey: key
          }),
          children: label
        }, key))
      })]
    })]
  });
}
ChatMessageBodyBase.displayName = 'ChatMessageBody';
const ChatMessageBody = exports.ChatMessageBody = /*#__PURE__*/(0, _react.memo)(ChatMessageBodyBase);