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;
const EditorWrapper = forwardRef(({ autofocus, editor, editorMode, enableSubmitInPreview, hidePreviewAfterSubmit, isFocused, markupHiddenActionsConfig: initialMarkupHiddenActionsConfig, markupToolbarConfig: initialMarkupToolbarConfig, qa, settingsVisible: settingsVisibleProp, showPreview, stickyToolbar, toggleShowPreview, toolbarsPreset, unsetShowPreview, wysiwygHiddenActionsConfig: initialWysiwygHiddenActionsConfig, wysiwygToolbarConfig: initialWysiwygToolbarConfig, }, ref) => {
    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 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 canRenderPreview = Boolean(editor.renderPreview && editorMode === 'markup' && !editor.splitModeEnabled);
    useKey((e) => canRenderPreview && isPreviewKeyDown(e), (e) => {
        e.preventDefault();
        onShowPreviewChange(!showPreview);
    }, { event: 'keydown' }, [showPreview, editorMode, onShowPreviewChange, canRenderPreview]);
    useKey((e) => Boolean(enableSubmitInPreview && showPreview && isFocused && isSubmitKeyDown(e)), () => {
        editor.emit('submit', null);
        if (hidePreviewAfterSubmit) {
            onShowPreviewChange(false);
        }
    }, { event: 'keydown' }, [hidePreviewAfterSubmit, enableSubmitInPreview, showPreview, showPreview]);
    const settingsProps = {
        mode: editorMode,
        onModeChange,
        onShowPreviewChange,
        onSplitModeChange,
        onToolbarVisibilityChange,
        renderPreviewButton: canRenderPreview,
        showPreview,
        splitMode: editor.splitMode,
        splitModeEnabled: editor.splitModeEnabled,
        stickyToolbar,
        toolbarVisibility: editor.toolbarVisible && !showPreview,
        disableMark: editor.mobile,
    };
    const areSettingsVisible = settingsVisibleProp === true ||
        (Array.isArray(settingsVisibleProp) && settingsVisibleProp.length > 0);
    const toolbarDisplay = editor.mobile ? 'scroll' : 'shrink';
    return (_jsx("div", { className: b('editor-wrapper'), ref: ref, "data-qa": qa, "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,
                    }) }), _jsx(Settings, { ...settingsProps, settingsVisible: settingsVisibleProp })] })) : (_jsxs(_Fragment, { children: [editorMode === 'wysiwyg' && (_jsx(WysiwygEditorView, { editor: editor, autofocus: autofocus, settingsVisible: areSettingsVisible, toolbarConfig: wysiwygToolbarConfig, toolbarVisible: editor.toolbarVisible, hiddenActionsConfig: wysiwygHiddenActionsConfig, className: b('editor', { mode: editorMode }), toolbarClassName: b('toolbar'), stickyToolbar: stickyToolbar, toolbarDisplay: toolbarDisplay, children: _jsx(Settings, { ...settingsProps, settingsVisible: editor.toolbarVisible && settingsVisibleProp }) })), editorMode === 'markup' && (_jsx(MarkupEditorView, { editor: editor, autofocus: autofocus, settingsVisible: areSettingsVisible, toolbarConfig: markupToolbarConfig, toolbarVisible: editor.toolbarVisible, splitMode: editor.splitMode, splitModeEnabled: editor.splitModeEnabled, hiddenActionsConfig: markupHiddenActionsConfig, className: b('editor', { mode: editorMode }), toolbarClassName: b('toolbar'), stickyToolbar: stickyToolbar, toolbarDisplay: toolbarDisplay, children: _jsx(Settings, { ...settingsProps, settingsVisible: editor.toolbarVisible && settingsVisibleProp }) })), _jsx(Settings, { ...settingsProps, settingsVisible: !editor.toolbarVisible && settingsVisibleProp, renderPreviewButton: !editor.toolbarVisible && canRenderPreview })] })) }));
});
EditorWrapper.displayName = 'EditorWrapper';
export const MarkdownEditorView = forwardRef((props, ref) => {
    const divRef = useEnsuredForwardedRef(ref);
    const editorWrapperRef = useRef(null);
    const [showPreview, , unsetShowPreview, toggleShowPreview] = useBooleanState(false);
    const [isMounted, setIsMounted] = useState(false);
    useEffect(() => {
        setIsMounted(true);
    }, []);
    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 { autofocus, className, enableSubmitInPreview = true, hidePreviewAfterSubmit = false, markupHiddenActionsConfig, markupToolbarConfig, qa, settingsVisible = true, stickyToolbar, toolbarsPreset, wysiwygHiddenActionsConfig, wysiwygToolbarConfig, } = props;
    const rerender = useUpdate();
    useLayoutEffect(() => {
        editor.on('rerender', rerender);
        return () => {
            editor.off('rerender', rerender);
        };
    }, [editor, rerender]);
    const editorMode = editor.currentMode;
    const markupSplitMode = editor.splitModeEnabled && editor.splitMode && editorMode === 'markup';
    const splitModeViewWrapperRef = useRef(null);
    const toaster = useToaster();
    useEffect(() => {
        if (showPreview) {
            divRef.current.focus();
        }
    }, [divRef, showPreview]);
    const areSettingsVisible = settingsVisible === true ||
        (Array.isArray(settingsVisible) && settingsVisible.length > 0);
    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: areSettingsVisible,
                split: markupSplitMode && editor.splitMode,
            }, [className]), role: "button", tabIndex: 0, children: [_jsx(EditorWrapper, { autofocus: autofocus, editor: editor, editorMode: editorMode, enableSubmitInPreview: enableSubmitInPreview, hidePreviewAfterSubmit: hidePreviewAfterSubmit, isFocused: isWrapperFocused(divRef), markupHiddenActionsConfig: markupHiddenActionsConfig, markupToolbarConfig: markupToolbarConfig, qa: "g-md-editor-mode", ref: editorWrapperRef, settingsVisible: settingsVisible, showPreview: showPreview, stickyToolbar: stickyToolbar, toggleShowPreview: toggleShowPreview, toolbarsPreset: toolbarsPreset, unsetShowPreview: unsetShowPreview, wysiwygHiddenActionsConfig: wysiwygHiddenActionsConfig, wysiwygToolbarConfig: wysiwygToolbarConfig }), 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
