import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
import { useToaster } from '@gravity-ui/uikit';
import { ErrorBoundary } from 'react-error-boundary';
import { useEnsuredForwardedRef, useKey, useUpdate } from 'react-use';
import { cn } from "../classname.js";
import { i18n } from "../i18n/bundle/index.js";
import { globalLogger } from "../logger.js";
import { useBooleanState, useSticky } from "../react-utils/index.js";
import { isMac } from "../utils/index.js";
import { HorizontalDrag } from "./HorizontalDrag.js";
import { MarkupEditorView } from "./MarkupEditorView.js";
import { SplitModeView } from "./SplitModeView.js";
import { WysiwygEditorView } from "./WysiwygEditorView.js";
import { useMarkdownEditorContext } from "./context.js";
import { EditorSettings } from "./settings/index.js";
import { stickyCn } from "./sticky/index.js";
import { getToolbarsConfigs } from "./toolbar/utils/toolbarsConfigs.js";
import "../styles/styles.css";
import "./MarkdownEditorView.css"; // eslint-disable-line import/order
export const cnEditorComponent = cn('editor-component');
const b = cnEditorComponent;
export const MarkdownEditorView = forwardRef((props, ref) => {
    const divRef = useEnsuredForwardedRef(ref);
    const [isMounted, setIsMounted] = useState(false);
    useEffect(() => {
        setIsMounted(true);
    }, []);
    const [showPreview, , unsetShowPreview, toggleShowPreview] = useBooleanState(false);
    const context = useMarkdownEditorContext();
    const editor = (props.editor ?? context);
    if (!editor)
        throw new Error('[MarkdownEditorView]: an instance of the editor must be passed through the props or context');
    const { qa, autofocus, className, settingsVisible = true, toolbarsPreset, stickyToolbar, wysiwygToolbarConfig: initialWysiwygToolbarConfig, markupToolbarConfig: initialMarkupToolbarConfig, wysiwygHiddenActionsConfig: initialWysiwygHiddenActionsConfig, markupHiddenActionsConfig: initialMarkupHiddenActionsConfig, enableSubmitInPreview = true, hidePreviewAfterSubmit = false, } = props;
    const { wysiwygToolbarConfig, markupToolbarConfig, wysiwygHiddenActionsConfig, markupHiddenActionsConfig, } = useMemo(() => getToolbarsConfigs({
        toolbarsPreset,
        props: {
            wysiwygToolbarConfig: initialWysiwygToolbarConfig,
            markupToolbarConfig: initialMarkupToolbarConfig,
            wysiwygHiddenActionsConfig: initialWysiwygHiddenActionsConfig,
            markupHiddenActionsConfig: initialMarkupHiddenActionsConfig,
        },
        preset: editor.preset,
    }), [
        toolbarsPreset,
        initialWysiwygToolbarConfig,
        initialMarkupToolbarConfig,
        initialWysiwygHiddenActionsConfig,
        initialMarkupHiddenActionsConfig,
        editor.preset,
    ]);
    const rerender = useUpdate();
    useLayoutEffect(() => {
        editor.on('rerender', rerender);
        return () => {
            editor.off('rerender', rerender);
        };
    }, [editor, rerender]);
    const onModeChange = useCallback((type) => {
        editor.changeEditorMode({ mode: type, reason: 'settings' });
        unsetShowPreview();
    }, [editor, unsetShowPreview]);
    const onToolbarVisibilityChange = useCallback((visible) => {
        editor.changeToolbarVisibility({ visible });
    }, [editor]);
    const onSplitModeChange = useCallback((splitModeEnabled) => {
        unsetShowPreview();
        editor.changeSplitModeEnabled({ splitModeEnabled });
    }, [editor, unsetShowPreview]);
    const onShowPreviewChange = useCallback((showPreviewValue) => {
        editor.changeSplitModeEnabled({ splitModeEnabled: false });
        if (showPreviewValue !== showPreview)
            toggleShowPreview();
    }, [editor, showPreview, toggleShowPreview]);
    const editorMode = editor.currentMode;
    const markupSplitMode = editor.splitModeEnabled && editor.splitMode && editorMode === 'markup';
    const canRenderPreview = Boolean(editor.renderPreview && editorMode === 'markup' && !editor.splitModeEnabled);
    useKey((e) => canRenderPreview && isPreviewKeyDown(e), (e) => {
        e.preventDefault();
        onShowPreviewChange(!showPreview);
    }, { event: 'keydown' }, [showPreview, editorMode, onShowPreviewChange, canRenderPreview]);
    const editorWrapperRef = useRef(null);
    const splitModeViewWrapperRef = useRef(null);
    useEffect(() => {
        if (showPreview) {
            divRef.current.focus();
        }
    }, [divRef, showPreview]);
    useKey((e) => enableSubmitInPreview &&
        showPreview &&
        isWrapperFocused(divRef) &&
        isSubmitKeyDown(e), () => {
        editor.emit('submit', null);
        if (hidePreviewAfterSubmit) {
            onShowPreviewChange(false);
        }
    }, { event: 'keydown' }, [hidePreviewAfterSubmit, enableSubmitInPreview, showPreview, showPreview]);
    const settings = useMemo(() => (_jsx(Settings, { mode: editorMode, settingsVisible: settingsVisible, onModeChange: onModeChange, toolbarVisibility: editor.toolbarVisible && !showPreview, onToolbarVisibilityChange: onToolbarVisibilityChange, onSplitModeChange: onSplitModeChange, splitModeEnabled: editor.splitModeEnabled, splitMode: editor.splitMode, stickyToolbar: stickyToolbar, onShowPreviewChange: onShowPreviewChange, showPreview: showPreview, renderPreviewButton: canRenderPreview })), [
        editorMode,
        settingsVisible,
        editor.toolbarVisible,
        editor.splitModeEnabled,
        editor.splitMode,
        onModeChange,
        showPreview,
        onToolbarVisibilityChange,
        onSplitModeChange,
        stickyToolbar,
        onShowPreviewChange,
        canRenderPreview,
    ]);
    const toaster = useToaster();
    return (_jsx(ErrorBoundary, { onError: (e) => {
            globalLogger.error(e);
            editor.logger.error(e);
        }, fallbackRender: ({ error, resetErrorBoundary }) => {
            toaster.add({
                theme: 'danger',
                name: 'g-md-editor-error',
                title: i18n('error-title'),
                content: error.message,
            });
            setTimeout(() => {
                resetErrorBoundary();
                editor.changeEditorMode({
                    mode: 'markup',
                    reason: 'error-boundary',
                    emit: false,
                });
            });
            return null;
        }, children: _jsxs("div", { ref: divRef, "data-qa": qa, className: b({
                settings: settingsVisible,
                split: markupSplitMode && editor.splitMode,
            }, [className]), role: "button", tabIndex: 0, children: [_jsx("div", { className: b('editor-wrapper'), ref: editorWrapperRef, "data-qa": "g-md-editor-mode", "data-mode": editor.currentMode, children: showPreview ? (_jsxs(_Fragment, { children: [_jsx("div", { className: b('preview-wrapper'), children: editor.renderPreview?.({
                                    getValue: editor.getValue,
                                    mode: 'preview',
                                    md: editor.mdOptions,
                                    directiveSyntax: editor.directiveSyntax,
                                }) }), settings] })) : (_jsxs(_Fragment, { children: [editorMode === 'wysiwyg' && (_jsx(WysiwygEditorView, { editor: editor, autofocus: autofocus, settingsVisible: settingsVisible, toolbarConfig: wysiwygToolbarConfig, toolbarVisible: editor.toolbarVisible, hiddenActionsConfig: wysiwygHiddenActionsConfig, className: b('editor', { mode: editorMode }), toolbarClassName: b('toolbar'), stickyToolbar: stickyToolbar, children: editor.toolbarVisible && settingsVisible && settings })), editorMode === 'markup' && (_jsx(MarkupEditorView, { editor: editor, autofocus: autofocus, settingsVisible: settingsVisible, toolbarConfig: markupToolbarConfig, toolbarVisible: editor.toolbarVisible, splitMode: editor.splitMode, splitModeEnabled: editor.splitModeEnabled, hiddenActionsConfig: markupHiddenActionsConfig, className: b('editor', { mode: editorMode }), toolbarClassName: b('toolbar'), stickyToolbar: stickyToolbar, children: editor.toolbarVisible && settings })), !editor.toolbarVisible && settings] })) }), markupSplitMode && (_jsxs(_Fragment, { children: [editor.splitMode === 'horizontal' ? (_jsx(HorizontalDrag, { editor: editor, isMounted: isMounted, leftElRef: editorWrapperRef, rightElRef: splitModeViewWrapperRef, wrapperRef: divRef })) : (_jsx("div", { className: b('resizer') })), _jsx(SplitModeView, { editor: editor, ref: splitModeViewWrapperRef })] }))] }) }));
});
MarkdownEditorView.displayName = 'MarkdownEditorView';
const MarkupSearchAnchor = ({ mode }) => (_jsx(_Fragment, { children: mode === 'markup' && _jsx("div", { className: "g-md-search-anchor" }) }));
function Settings(props) {
    const wrapperRef = useRef(null);
    const isSticky = useSticky(wrapperRef) && props.toolbarVisibility && props.stickyToolbar;
    return (_jsx(_Fragment, { children: (props.renderPreviewButton || props.settingsVisible) && (_jsx("div", { className: b('settings-wrapper'), children: _jsxs("div", { ref: wrapperRef, className: stickyCn.settings({
                    withToolbar: props.toolbarVisibility,
                    stickyActive: isSticky,
                }), children: [_jsx(EditorSettings, { ...props }), _jsx(MarkupSearchAnchor, { ...props })] }) })) }));
}
function isPreviewKeyDown(e) {
    const modKey = isMac() ? e.metaKey : e.ctrlKey;
    return modKey && e.shiftKey && e.code === 'KeyP';
}
function isWrapperFocused(divRef) {
    return document.activeElement === divRef.current;
}
function isSubmitKeyDown(e) {
    const modKey = isMac() ? e.metaKey : e.ctrlKey;
    return modKey && e.code === 'Enter';
}
//# sourceMappingURL=MarkdownEditorView.js.map
