"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandHandler = void 0;
const lodash_1 = require("../../../lodash.js");
const logger_1 = require("../../../logger.js");
const autocomplete_popup_1 = require("../../../utils/autocomplete-popup.js");
const carousel_1 = require("../../../utils/carousel/index.js");
const Autocomplete_1 = require("../Autocomplete/index.js");
const ReactRenderer_1 = require("../ReactRenderer/index.js");
const component_1 = require("./component.js");
const utils_1 = require("./utils.js");
class CommandHandler {
    #logger;
    #actions;
    #actionStorage;
    #nodesIgnoreList;
    #filteredActionsCarousel;
    #view;
    #anchor = null;
    #range;
    #filterText;
    #popupCloser;
    #menuProps;
    #menuRenderItem;
    constructor({ logger, actions, storage, nodesIgnoreList = [] }) {
        this.#logger = logger;
        this.#actions = actions;
        this.#actionStorage = storage;
        this.#nodesIgnoreList = nodesIgnoreList;
    }
    onOpen(action) {
        this.findAnchor();
        if (!this.#anchor || this.shouldIgnore(action)) {
            this.closeAutocomplete(action.view);
            return true;
        }
        this.#popupCloser = new autocomplete_popup_1.AutocompletePopupCloser(action.view);
        this.updateState(action);
        this.filterActions();
        this.render();
        return true;
    }
    onFilter(action) {
        if (this.shouldIgnore(action) || action.filter?.endsWith('  ')) {
            this.closeAutocomplete(action.view);
            return true;
        }
        this.updateState(action);
        this.#filterText = action.filter?.trim().toLowerCase();
        const needToClose = this.filterActions();
        this.render();
        if (needToClose) {
            this.closeAutocomplete(action.view);
        }
        return true;
    }
    onArrow(action) {
        if (this.shouldIgnore(action)) {
            (0, Autocomplete_1.closeAutocomplete)(action.view);
            return true;
        }
        this.updateState(action);
        if (!this.#filteredActionsCarousel)
            return false;
        switch (action.kind) {
            case Autocomplete_1.AutocompleteActionKind.up: {
                this.#filteredActionsCarousel.prev();
                break;
            }
            case Autocomplete_1.AutocompleteActionKind.down: {
                this.#filteredActionsCarousel.next();
                break;
            }
            default:
                return false;
        }
        this.render();
        return true;
    }
    onEnter(action) {
        if (this.shouldIgnore(action)) {
            (0, Autocomplete_1.closeAutocomplete)(action.view);
            return true;
        }
        this.updateState(action);
        this.select();
        return true;
    }
    onClose(action) {
        this.updateState(action);
        this.clear();
        return true;
    }
    onDestroy() {
        this.clear();
    }
    closeAutocomplete(view) {
        setTimeout(() => {
            (0, Autocomplete_1.closeAutocomplete)(view);
        });
    }
    shouldIgnore(action) {
        const parentType = action.view.state.doc.resolve(action.range.from).parent.type;
        return (parentType.spec.commandMenu === false || this.#nodesIgnoreList.includes(parentType.name));
    }
    select() {
        if (!this.#view || !this.#range)
            return;
        const action = this.#filteredActionsCarousel?.currentItem;
        if (!action)
            return;
        const view = this.#view;
        const range = this.#range;
        view.dispatch(view.state.tr.deleteRange(range.from, range.to).scrollIntoView());
        action.exec(this.#actionStorage);
        view.focus();
        logger_1.globalLogger.action({ mode: 'wysiwyg', source: 'command-menu', action: action.id });
        this.#logger.action({ source: 'command-menu', action: action.id });
    }
    filterActions() {
        const currentItem = this.#filteredActionsCarousel?.currentItem;
        const inputText = this.#filterText;
        const enabledActions = this.#actions.filter((action) => action.isEnable(this.#actionStorage));
        let filteredActions = enabledActions;
        let needToClose = false;
        if (inputText) {
            filteredActions = filterActions(enabledActions, inputText);
            needToClose = !filteredActions.length && needToHide(enabledActions, inputText);
        }
        this.#filteredActionsCarousel = new carousel_1.ArrayCarousel(filteredActions);
        if (currentItem) {
            const newIndex = this.#filteredActionsCarousel.array.findIndex((item) => item === currentItem);
            if (newIndex !== -1) {
                this.#filteredActionsCarousel.currentIndex = newIndex;
            }
        }
        return needToClose;
    }
    render() {
        this.findAnchor();
        const viewItems = this.#filteredActionsCarousel?.array ?? [];
        this.#menuProps = {
            anchorElement: this.#anchor,
            currentIndex: this.#filteredActionsCarousel?.currentIndex,
            items: viewItems,
            onItemClick: this.onItemClick,
            onOpenChange: this.#popupCloser?.popupOpenChangeHandler,
        };
        this.#menuRenderItem = this.#menuRenderItem ?? this.createMenuRenderItem();
        this.#menuRenderItem.rerender();
    }
    onItemClick = (index) => {
        if (this.#filteredActionsCarousel) {
            this.#filteredActionsCarousel.currentIndex = index;
            this.select();
        }
        this.#view?.focus();
    };
    updateState({ view, range }) {
        this.#view = view;
        this.#range = range;
    }
    clear() {
        this.#view = undefined;
        this.#range = undefined;
        this.#anchor = null;
        this.#filterText = undefined;
        this.#filteredActionsCarousel = undefined;
        this.#popupCloser?.cancelTimer();
        this.#popupCloser = undefined;
        this.#menuProps = undefined;
        this.#menuRenderItem?.remove();
        this.#menuRenderItem = undefined;
    }
    createMenuRenderItem() {
        return (0, ReactRenderer_1.getReactRendererFromState)(this.#view.state).createItem('command_menu', () => this.#menuProps ? (0, component_1.render)(this.#menuProps) : null);
    }
    findAnchor() {
        this.#anchor = (0, utils_1.findDecoElem)(this.#view?.dom);
    }
}
exports.CommandHandler = CommandHandler;
function filterActions(actions, text) {
    return actions.filter((action) => action.id.toLowerCase().includes(text) ||
        ((0, lodash_1.isFunction)(action.title) ? action.title() : action.title).toLowerCase().includes(text));
}
const CHARS_TO_HIDE = 4;
function needToHide(actions, text) {
    let iter = 1;
    do {
        const prevInput = text.slice(0, text.length - iter);
        const prevActions = filterActions(actions, prevInput);
        if (prevActions.length)
            break;
        iter++;
    } while (iter < text.length && iter < CHARS_TO_HIDE);
    return iter >= CHARS_TO_HIDE;
}
//# sourceMappingURL=handler.js.map
