import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { useCallback } from 'react';
import { Popup } from '@gravity-ui/uikit';
import { Slice } from 'prosemirror-model';
import { TextSelection } from 'prosemirror-state';
import { useMount } from 'react-use';
import { cn } from "../../../../classname.js";
import { getReactRendererFromState } from "../../../behavior/index.js";
import { GptDialog } from "../GptDialog/GptDialog.js";
import { WIDGET_DECO_CLASS_NAME, WIDGET_DECO_SPEC_FLAG, gptPopupPlacement } from "../constants.js";
import { pluginKey } from "../plugin.js";
import "./view.css";
export const cnGptPopup = cn('gpt-popup');
export class GptWidgetDecoView {
    _view;
    _renderer;
    _decoElem = null;
    _params;
    _serializer;
    _parser;
    _confirmOpen;
    constructor(view, params) {
        this._view = view;
        this._params = params;
        this._serializer = params.serializer;
        this._parser = params.parser;
        this._confirmOpen = false;
        this._renderer = getReactRendererFromState(view.state).createItem('gpt-widget-view', this._render.bind(this));
    }
    update(view, prevState) {
        const { state, dispatch } = view;
        if (this._decoElem && !state.selection.eq(prevState.selection)) {
            const transaction = state.tr;
            const meta = { action: 'hide' };
            dispatch(transaction.setMeta(pluginKey, meta));
            this._view.focus();
            return;
        }
        const decoElements = Array.from(view.dom.querySelectorAll(`.${WIDGET_DECO_CLASS_NAME}`));
        this._decoElem = decoElements.at(-1) ?? null;
        this._renderer.rerender();
    }
    destroy() {
        this._resetState();
        this._renderer.remove();
    }
    _resetState() {
        this._decoElem = null;
        this._confirmOpen = false;
    }
    _onConfirmCancel = () => {
        this._confirmOpen = false;
        this._renderer.rerender();
    };
    _onConfirmOk = () => {
        this._onClose();
    };
    _render() {
        if (!this._decoElem)
            return null;
        const markup = this._getContentOfDecoration();
        if (markup === undefined) {
            return null;
        }
        return (_jsx(Widget, { markup: markup, anchorElement: this._decoElem, answerRender: this._params.answerRender, promptPresets: this._params.promptPresets, disablePromptPresets: this._params.disablePromptPresets, customPromptPlaceholder: this._params.customPromptPlaceholder, disabledPromptPlaceholder: this._params.disabledPromptPlaceholder, gptAlertProps: this._params.gptAlertProps, onApplyResult: this._onSubmit, onCustomPromptApply: this._params.onCustomPromptApply, onPromptPresetClick: this._params.onPromptPresetClick, onTryAgain: this._params.onTryAgain, onLike: this._params.onLike, onDislike: this._params.onDislike, onClose: this._onClose, onUpdate: this._onGptAnswerUpdate, confirmOpen: this._confirmOpen, onConfirmOk: this._onConfirmOk, onConfirmCancel: this._onConfirmCancel }));
    }
    _onGptAnswerUpdate = (answer) => {
        this._params.onUpdate?.(answer);
    };
    _onSubmit = (answer) => {
        const deco = this._getCurrentDecoration();
        if (!deco)
            return;
        const { from, to } = deco;
        const answerNode = this._parser.parse(answer);
        const tr = this._view.state.tr;
        const meta = { action: 'hide' };
        tr.setMeta(pluginKey, meta);
        tr.replace(from, to, new Slice(answerNode.content, 1, 1));
        tr.setSelection(TextSelection.create(tr.doc, tr.mapping.map(to)));
        this._view.dispatch(tr);
        setTimeout(() => {
            this._view.focus();
        }, 0);
        this._params.onApplyResult?.(answer);
        this._resetState();
    };
    _onClose = () => {
        const deco = this._getCurrentDecoration();
        if (!deco) {
            return;
        }
        const tr = this._view.state.tr;
        const meta = { action: 'hide' };
        tr.setSelection(TextSelection.create(tr.doc, deco.from, deco.to));
        tr.setMeta(pluginKey, meta);
        this._view.dispatch(tr);
        setTimeout(() => {
            this._view.focus();
        }, 0);
        this._params.onClose?.();
        this._resetState();
    };
    _getContentOfDecoration() {
        const deco = this._getCurrentDecoration();
        if (!deco)
            return undefined;
        const { from, to } = deco;
        try {
            // FIXME: Verify and use Node instead of Fragment
            const fragment = this._view.state.doc.slice(from, to, true).content;
            const yfmMarkup = this._serializer.serialize(fragment);
            return yfmMarkup;
        }
        catch (error) {
            console.error(error);
            return this._view.state.doc.textBetween(from, to, '\n', '');
        }
    }
    _getCurrentDecoration() {
        return this._getPluginState()?.find(undefined, undefined, 
        // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
        (spec) => spec[WIDGET_DECO_SPEC_FLAG])[0];
    }
    _getPluginState() {
        return pluginKey.getState(this._view.state);
    }
}
function Widget({ markup, anchorElement, answerRender, promptPresets, disablePromptPresets, customPromptPlaceholder, disabledPromptPlaceholder, onCustomPromptApply, onApplyResult, onPromptPresetClick, onTryAgain, onLike, onDislike, onClose, onUpdate, gptAlertProps, }) {
    useMount(() => {
        if (anchorElement && 'scrollIntoView' in anchorElement) {
            anchorElement.scrollIntoView({
                behavior: 'smooth',
                block: 'center',
            });
        }
    });
    const handleUpdate = useCallback((result) => {
        onUpdate?.(result);
    }, [onUpdate]);
    return (_jsx(_Fragment, { children: _jsx(Popup, { className: cnGptPopup(), open: true, anchorElement: anchorElement, placement: gptPopupPlacement, onOpenChange: (open) => {
                if (!open)
                    onClose();
            }, strategy: "absolute", children: _jsx("div", { className: cnGptPopup('content'), children: _jsx(GptDialog, { markup: markup, answerRender: answerRender, promptPresets: promptPresets, disablePromptPresets: disablePromptPresets, customPromptPlaceholder: customPromptPlaceholder, disabledPromptPlaceholder: disabledPromptPlaceholder, onApplyResult: onApplyResult, onCustomPromptApply: onCustomPromptApply, onPromptPresetClick: onPromptPresetClick, onTryAgain: onTryAgain, onLike: onLike, onDislike: onDislike, onClose: onClose, onUpdate: handleUpdate, gptAlertProps: gptAlertProps }) }) }) }));
}
//# sourceMappingURL=view.js.map
