import React, { useMemo, useRef, useContext, useState, useEffect, useCallback } from 'react';
import classnames from 'classnames';
import isEqual from 'lodash-es/isEqual';
import { withHistory } from 'slate-history';
import { ValidityMessages, getErrorAriaAttributes, useDefaultValidationValues } from '../form-field';
import { resetNodes, CharactersCounter, withMaxLength } from '../chat';
import { TextEditorToolbar } from './text-editor-toolbar';
import TextEditorContext from './text-editor-context';
import TextEditorHeader from './text-editor-header';
import TextEditorContent, { Element as ContentElement, Leaf as ContentLeaf } from './text-editor-content';
import withLinks from './hooks/with-links';
import TextEditorLoader from './text-editor-loader';
import { TEXT_EDITOR_DEFAULT_VALUE, TEXT_EDITOR_DEFAULT_TOOLS, TOOLBAR_POSITION, INLINE_EDITOR_TYPES, HEADER_HEIGHT } from './text-editor-constants';
import { useTextEditorDefaultTranslations } from './text-editor-hooks';
import { getTextEditorValueLength } from './text-editor-helpers';
import { useTranslation } from '../hooks/use-translation';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
function TextEditorComponent({
  name,
  type,
  header,
  value = null,
  initialValue = null,
  label = '',
  toolbarLabels,
  toolbarPosition = TOOLBAR_POSITION.TOP,
  onCancel,
  onSave,
  onFocus,
  onBlur,
  validity = null,
  placeholder = '',
  autoFocus = false,
  readOnly = false,
  height = 250,
  contentTestId = 'text-editor-content',
  contentAriaLabel,
  enabledTools = TEXT_EDITOR_DEFAULT_TOOLS,
  elementRender = ContentElement,
  leafRender = ContentLeaf,
  onChange = () => {},
  deleteEditorContentButtonAriaLabel,
  id = '',
  maxLength,
  getCharactersCounterString
}) {
  const {
    t
  } = useTranslation();
  const {
    slate,
    slateReact
  } = useContext(TextEditorContext);
  const validationValues = useDefaultValidationValues();
  const {
    Editor,
    Transforms,
    createEditor
  } = slate;
  const {
    withReact,
    Slate
  } = slateReact;
  const getCharactersCounterStringText = useCallback(count => {
    if (getCharactersCounterString) {
      return getCharactersCounterString(count);
    }
    return t('{{count}} characters remaining', {
      count
    });
  }, [getCharactersCounterString]);
  const editor = useMemo(() => withMaxLength(maxLength)(withLinks(withHistory(withReact(createEditor())))), [maxLength]);
  const selection = useRef(null);
  const slateValue = value || initialValue || TEXT_EDITOR_DEFAULT_VALUE;
  useEffect(() => {
    if (!isEqual(editor.children, slateValue)) {
      // Update the cached value inside the editor
      resetNodes(editor, slateValue);
    }
  }, [slateValue, editor]);
  function saveSelection() {
    selection.current = editor.selection;
    setTimeout(() => onBlur?.(), 0);
  }
  function recoverSelection() {
    if (!editor.selection && editor.children.length > 0) {
      Transforms.select(editor, selection.current || Editor.end(editor, []));
    }
    setTimeout(() => onFocus?.(), 0);
  }
  const errorAttr = getErrorAriaAttributes({
    validity,
    id,
    validationValues
  });
  const ariaLabel = contentAriaLabel || label;
  const ariaAttrs = {
    ...errorAttr,
    ...(ariaLabel && {
      'aria-label': ariaLabel
    })
  };
  const toolbarMemo = useMemo(() => /*#__PURE__*/_jsx(TextEditorToolbar, {
    enabledTools: enabledTools,
    labels: toolbarLabels,
    position: toolbarPosition,
    onCancel: onCancel,
    onSave: onSave
  }), [enabledTools, toolbarLabels, toolbarPosition, onCancel, onSave]);
  const isFlex = type === INLINE_EDITOR_TYPES.FLEX;
  const styleHeight = header?.title === 'string' || header?.hasDeleteButton ? height + HEADER_HEIGHT : height;
  return /*#__PURE__*/_jsxs(_Fragment, {
    children: [label && /*#__PURE__*/_jsx("label", {
      htmlFor: name,
      className: "text-editor-label",
      children: label
    }), /*#__PURE__*/_jsx("div", {
      className: classnames('text-editor-wrapper', isFlex && 'is-flex'),
      "test-id": "text-editor-wrapper"
      /* eslint-disable-next-line react/forbid-dom-props */,
      style: {
        height: !isFlex ? styleHeight : undefined
      },
      children: /*#__PURE__*/_jsxs(Slate, {
        editor: editor,
        initialValue: slateValue,
        onChange: newValue => onChange(newValue),
        onBlur: saveSelection,
        children: [!!header && /*#__PURE__*/_jsx(TextEditorHeader, {
          title: header.title,
          titlePlaceholder: header.titlePlaceholder,
          onChangeTitle: header.onChangeTitle,
          isEditable: !!header.isEditable,
          hasDeleteButton: header.hasDeleteButton,
          onDelete: header.onDelete,
          deleteEditorContentButtonAriaLabel: deleteEditorContentButtonAriaLabel,
          inputAriaLabel: header.inputAriaLabel,
          maxLength: header.maxLength
        }), toolbarPosition === TOOLBAR_POSITION.TOP && toolbarMemo, /*#__PURE__*/_jsx(TextEditorContent, {
          placeholder: placeholder,
          readOnly: readOnly,
          autoFocus: autoFocus,
          testId: contentTestId,
          elementRender: elementRender,
          leafRender: leafRender,
          onBlur: saveSelection,
          onFocus: recoverSelection,
          ariaAttrs: ariaAttrs,
          maxLength: maxLength
        }), toolbarPosition === TOOLBAR_POSITION.BOTTOM && toolbarMemo]
      })
    }), maxLength && /*#__PURE__*/_jsx(CharactersCounter, {
      currLength: getTextEditorValueLength(slateValue),
      maxLength: maxLength,
      getCharactersCounterString: getCharactersCounterStringText
    }), validity && /*#__PURE__*/_jsx(ValidityMessages, {
      validity: validity,
      validationTestId: `${name}-validity`,
      fieldId: id
    })]
  });
}
/**
 * @midnight-gray-supported
 * @alpine-light-supported
 * */
export default function TextEditor({
  name,
  header,
  type,
  value = null,
  initialValue = null,
  validity = null,
  label = '',
  placeholder = '',
  autoFocus = false,
  readOnly = false,
  testId = 'text-editor',
  contentTestId = 'text-editor-content',
  contentAriaLabel,
  className = '',
  height = 250,
  enabledTools = TEXT_EDITOR_DEFAULT_TOOLS,
  toolbarPosition = TOOLBAR_POSITION.TOP,
  elementRender = ContentElement,
  leafRender = ContentLeaf,
  onChange = () => {},
  onCancel,
  onSave,
  tooltipTextBold,
  tooltipTextItalic,
  tooltipTextUnderline,
  tooltipTextSuperscript,
  tooltipTextLink,
  tooltipTextRemoveLink,
  tooltipTextBulletedList,
  tooltipTextNumberedList,
  tooltipTextClearFormatting,
  tooltipTextCode,
  urlIsRequiredMessage,
  enterValidUrlMessage,
  saveButtonText,
  headingLargeText,
  headingMediumText,
  headingSmallText,
  regularText,
  validationErrorWarningMessage,
  linkInputLabelText,
  deleteEditorContentButtonAriaLabel,
  id = '',
  maxLength,
  getCharactersCounterString
}) {
  const [isFocused, setIsFocused] = useState(false);
  const defaultTranslations = useTextEditorDefaultTranslations();
  const consumerTranslations = {
    tooltipTextBold,
    tooltipTextItalic,
    tooltipTextUnderline,
    tooltipTextSuperscript,
    tooltipTextLink,
    tooltipTextRemoveLink,
    tooltipTextBulletedList,
    tooltipTextNumberedList,
    tooltipTextClearFormatting,
    tooltipTextCode,
    urlIsRequiredMessage,
    enterValidUrlMessage,
    saveButtonText,
    headingLargeText,
    headingMediumText,
    headingSmallText,
    regularText,
    validationErrorWarningMessage,
    linkInputLabelText
  };
  const toolbarLabels = {
    ...defaultTranslations,
    ...Object.fromEntries(Object.entries(consumerTranslations).filter(([, v]) => typeof v !== 'undefined'))
  };
  return /*#__PURE__*/_jsx("div", {
    className: classnames('text-editor', isFocused && 'is-focused', className),
    "test-id": testId,
    children: /*#__PURE__*/_jsx(TextEditorLoader, {
      children: /*#__PURE__*/_jsx(TextEditorComponent, {
        type: type,
        name: name,
        header: header,
        value: value,
        onFocus: () => setIsFocused(true),
        onBlur: () => setIsFocused(false),
        initialValue: initialValue,
        validity: validity,
        label: label,
        toolbarLabels: toolbarLabels,
        toolbarPosition: toolbarPosition,
        onCancel: onCancel,
        onSave: onSave,
        placeholder: placeholder,
        autoFocus: autoFocus,
        readOnly: readOnly,
        height: height,
        contentTestId: contentTestId,
        contentAriaLabel: contentAriaLabel,
        enabledTools: enabledTools,
        elementRender: elementRender,
        leafRender: leafRender,
        onChange: onChange,
        deleteEditorContentButtonAriaLabel: deleteEditorContentButtonAriaLabel,
        id: id,
        maxLength: maxLength,
        getCharactersCounterString: getCharactersCounterString
      })
    })
  });
}