import * as VTable_editors from "@visactor/vtable-editors";

import { FormulaAutocomplete } from "./formula-autocomplete";

import { detectFunctionParameterPosition } from "./formula-helper";

export class FormulaInputEditor extends VTable_editors.InputEditor {
    constructor() {
        super(...arguments), this.formulaAutocomplete = null, this.sheet = null;
    }
    setSheet(sheet) {
        this.sheet = sheet;
    }
    getInputElement() {
        return this.element;
    }
    targetIsOnEditor(target) {
        return target === this.element || target === this.sheet.formulaUIManager.formulaInput;
    }
    createElement() {
        if (super.createElement(), this.element && this.sheet) {
            [ "click", "mouseup", "keyup", "select", "input", "focus" ].forEach((eventType => {
                const handler = e => {
                    const cursorPos = this.element.selectionStart;
                    null != cursorPos && (this.sheet.formulaManager.lastKnownCursorPosInFormulaInput = cursorPos, 
                    this.sheet.formulaManager.inputingElement = this.element);
                };
                this.element.addEventListener(eventType, handler), this.eventHandlers.push({
                    type: eventType,
                    handler: handler
                });
            }));
            const inputHandler = e => {
                this.handleFormulaInput(e);
            };
            this.element.addEventListener("input", inputHandler), this.eventHandlers.push({
                type: "input",
                handler: inputHandler
            }), setTimeout((() => {
                this.initAutocomplete();
            }), 50);
        }
    }
    handleFormulaInput(event) {
        if (!this.sheet || !this.element) return;
        const value = this.element.value;
        this.sheet.formulaUIManager.formulaInput.value = value;
        const highlightManager = this.sheet.formulaManager.cellHighlightManager;
        highlightManager && (value.startsWith("=") ? highlightManager.highlightFormulaCells(value) : highlightManager.clearHighlights());
    }
    initAutocomplete() {
        if (!this.sheet || !this.element) return;
        this.formulaAutocomplete && (this.formulaAutocomplete.release(), this.formulaAutocomplete = null);
        const tableContainer = this.sheet.getContentElement();
        this.formulaAutocomplete = new FormulaAutocomplete(tableContainer, this.sheet);
        this.formulaAutocomplete.attachTo(this.element, (item => {
            this.handleAutocompleteSelect(item);
        }), (() => {
            if (!this.formulaAutocomplete || !this.element) return;
            const inputRect = this.element.getBoundingClientRect(), containerRect = tableContainer.getBoundingClientRect(), windowHeight = window.innerHeight, relativeLeft = inputRect.left - containerRect.left, idealWidth = Math.max(300, inputRect.width);
            let relativeTop = inputRect.bottom - containerRect.top + 2;
            const spaceBelow = windowHeight - inputRect.bottom, spaceAbove = inputRect.top;
            spaceBelow < 250 && spaceAbove > spaceBelow && (relativeTop = inputRect.top - containerRect.top - 250 - 2);
            const bottomOverflow = relativeTop + 250 - containerRect.height;
            bottomOverflow > 0 && (relativeTop = Math.max(0, relativeTop - bottomOverflow)), 
            relativeTop < 0 && (relativeTop = 0);
            const dropdown = this.formulaAutocomplete.dropdown;
            dropdown && (dropdown.style.position = "absolute", dropdown.style.left = `${Math.max(0, relativeLeft)}px`, 
            dropdown.style.top = `${relativeTop}px`, dropdown.style.width = `${idealWidth}px`, 
            dropdown.style.maxHeight = "250px", dropdown.style.overflowY = "auto", dropdown.style.zIndex = "10000", 
            dropdown.style.boxShadow = "0 2px 8px rgba(0, 0, 0, 0.15)");
        }));
    }
    handleAutocompleteSelect(item) {
        if (!this.element || !this.sheet) return;
        this.element.value = "=" + item.value, this.sheet.formulaUIManager.formulaInput.value = this.element.value;
        const highlightManager = this.sheet.formulaManager.cellHighlightManager;
        highlightManager && this.element.value.startsWith("=") && highlightManager.highlightFormulaCells(this.element.value);
    }
    onStart(context) {
        var _a, _b;
        const formula = this.sheet.formulaManager.getCellFormula({
            sheet: (null === (_a = this.sheet.getActiveSheet()) || void 0 === _a ? void 0 : _a.getKey()) || "",
            row: context.row,
            col: context.col
        });
        if (formula && (context.value = formula), super.onStart(context), this.sheet.formulaManager.inputingElement = this.element, 
        this.sheet && "string" == typeof context.value) {
            const formula = this.sheet.formulaManager.getCellFormula({
                sheet: (null === (_b = this.sheet.getActiveSheet()) || void 0 === _b ? void 0 : _b.getKey()) || "",
                row: context.row,
                col: context.col
            });
            if (formula) {
                this.setValue(formula);
                const highlightManager = this.sheet.formulaManager.cellHighlightManager;
                highlightManager && highlightManager.highlightFormulaCells(formula);
            }
        }
    }
    beforeEnd() {
        this.sheet.formulaManager.formulaWorkingOnCell = null;
    }
    onEnd() {
        if (this.formulaAutocomplete && (this.formulaAutocomplete.release(), this.formulaAutocomplete = null), 
        this.sheet) {
            const highlightManager = this.sheet.formulaManager.cellHighlightManager;
            highlightManager && highlightManager.clearHighlights();
        }
        this.element && this.eventHandlers.forEach((({type: type, handler: handler}) => {
            this.element.removeEventListener(type, handler);
        })), super.onEnd();
    }
    getValue() {
        var _a;
        return (null === (_a = this.element) || void 0 === _a ? void 0 : _a.value) || "";
    }
    validateValue(newValue, oldValue, position, table, isClickOnTable) {
        var _a;
        if (isClickOnTable && newValue && newValue.startsWith("=")) {
            if (this.sheet) {
                const formulaInput = this.element;
                return this.sheet.formulaManager.inputIsParamMode = detectFunctionParameterPosition(formulaInput.value, this.sheet.formulaManager.lastKnownCursorPosInFormulaInput), 
                this.sheet.formulaManager.inputIsParamMode.inParamMode ? (this.sheet.formulaManager.formulaWorkingOnCell = null === (_a = this.sheet.getActiveSheet()) || void 0 === _a ? void 0 : _a.editingCell, 
                VTable_editors.ValidateEnum.validateNotExit) : VTable_editors.ValidateEnum.validateExit;
            }
            if ((newValue.match(/\(/g) || []).length !== (newValue.match(/\)/g) || []).length) return VTable_editors.ValidateEnum.validateNotExit;
        }
        return !0;
    }
    getCellRangeString(range) {
        if (!range || !range.start || !range.end) return "";
        const colToLetter = col => {
            let letter = "";
            for (;col >= 0; ) letter = String.fromCharCode(65 + col % 26) + letter, col = Math.floor(col / 26) - 1;
            return letter;
        }, startCol = colToLetter(range.start.col), startRow = range.start.row + 1, endCol = colToLetter(range.end.col), endRow = range.end.row + 1;
        return startCol === endCol && startRow === endRow ? `${startCol}${startRow}` : `${startCol}${startRow}:${endCol}${endRow}`;
    }
}

export const formulaEditor = new FormulaInputEditor;
//# sourceMappingURL=formula-editor.js.map