"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mGptPlugin = mGptPlugin;
const view_1 = require("@codemirror/view");
const view_2 = require("../../../../cm/view.js");
const markup_1 = require("../../../../markup/index.js");
const constants_1 = require("../constants.js");
const utils_1 = require("../utils.js");
const commands_1 = require("./commands.js");
const effects_1 = require("./effects.js");
const popup_1 = require("./popup.js");
class SpanWidget extends view_1.WidgetType {
    className = '';
    textContent = '';
    constructor(className, textContent) {
        super();
        this.className = className;
        this.textContent = textContent;
    }
    toDOM() {
        const spanElem = document.createElement('span');
        spanElem.className = this.className;
        spanElem.textContent = this.textContent;
        return spanElem;
    }
}
function mGptPlugin(gptProps) {
    return view_2.ViewPlugin.fromClass(class {
        _view;
        _renderItem;
        _anchor = null;
        decos = view_2.Decoration.none;
        disablePromptPresets = true;
        markup = null;
        selectedPosition = {
            from: 0,
            to: 0,
        };
        constructor(view) {
            this._view = view;
            this._renderItem = view.state
                .facet(markup_1.ReactRendererFacet)
                .createItem('gpt-in-markup-mode', () => this.renderPopup());
        }
        update(update) {
            if (update.docChanged || update.selectionSet) {
                this.decos = view_2.Decoration.none;
                return;
            }
            this.decos = this.decos.map(update.changes);
            const { from, to } = update.state.selection.main;
            this.selectedPosition.from = from;
            this.selectedPosition.to = to;
            for (const tr of update.transactions) {
                for (const eff of tr.effects) {
                    if (eff.is(effects_1.ShowMarkupGptEffect)) {
                        this._setSelectedText(this._getDecorationText(update, from, to));
                        if (from === to) {
                            this.disablePromptPresets = true;
                            if ((0, utils_1.isEmptyGptPrompts)(gptProps, true))
                                return;
                            const decorationWidget = view_2.Decoration.widget({
                                widget: new SpanWidget(constants_1.WIDGET_DECO_CLASS_NAME, ' '),
                            });
                            this.decos = view_2.Decoration.set([decorationWidget.range(from)]);
                            return;
                        }
                        this.disablePromptPresets = false;
                        if ((0, utils_1.isEmptyGptPrompts)(gptProps, false))
                            return;
                        this.decos = view_2.Decoration.set([
                            {
                                from,
                                to,
                                value: view_2.Decoration.mark({ class: constants_1.WIDGET_DECO_CLASS_NAME }),
                            },
                        ]);
                    }
                    if (eff.is(effects_1.HideMarkupGptEffect)) {
                        this.decos = view_2.Decoration.none;
                    }
                }
            }
        }
        docViewUpdate() {
            this._anchor = this._view.dom
                .getElementsByClassName(constants_1.WIDGET_DECO_CLASS_NAME)
                .item(0);
            this._renderItem.rerender();
        }
        destroy() {
            this._clearSelectedText();
            this._renderItem.remove();
        }
        renderPopup() {
            if (!this._anchor || this.markup === null) {
                return null;
            }
            return (0, popup_1.renderPopup)(this._anchor, {
                ...gptProps,
                disablePromptPresets: this.disablePromptPresets,
                onClose: () => (0, commands_1.hideMarkupGpt)(this._view),
                markup: this.markup,
                onApplyResult: (changedMarkup) => this._onApplyResult(changedMarkup),
            });
        }
        _getDecorationText(update, from, to) {
            return update.state.doc.sliceString(from, to);
        }
        _clearSelectedText() {
            this.markup = null;
        }
        _setSelectedText(str) {
            this.markup = str;
        }
        _onApplyResult(changedMarkup) {
            const { from, to } = this.selectedPosition;
            const changes = [{ from: from, to: to, insert: changedMarkup }];
            const transaction = this._view.state.update({
                changes: changes,
                effects: [effects_1.HideMarkupGptEffect.of(null)],
            });
            this._view.dispatch(transaction);
        }
    }, {
        decorations: (value) => value.decos,
    });
}
//# sourceMappingURL=plugin.js.map
