"use strict";

Object.defineProperty(exports, "__esModule", {
    value: !0
}), exports.WorkSheet = void 0;

const vtable_1 = require("@visactor/vtable"), vutils_1 = require("@visactor/vutils"), event_target_1 = require("../event/event-target"), ts_types_1 = require("../ts-types"), tools_1 = require("../tools"), ts_types_2 = require("../ts-types");

class WorkSheet extends event_target_1.EventTarget {
    constructor(sheet, options) {
        super(), this.selection = null, this.editingCell = null, this.resizeTimer = null, 
        this.isResizing = !1, this.options = options, this.container = options.container, 
        this.sheetKey = options.sheetKey, this.sheetTitle = options.sheetTitle, this.vtableSheet = sheet, 
        this.element = this._createRootElement(), this.container.appendChild(this.element), 
        this._initializeTable(), this._setupEventListeners();
    }
    get rowCount() {
        const data = this.getData();
        return data ? data.length : 0;
    }
    get colCount() {
        const data = this.getData();
        return data && data.length > 0 ? data[0].length : 0;
    }
    getRowCount() {
        return this.tableInstance.rowCount;
    }
    getColumnCount() {
        return this.tableInstance.colCount;
    }
    get records() {
        return this.getData();
    }
    get columns() {
        return this.options.columns || [];
    }
    _createRootElement() {
        const element = document.createElement("div");
        element.setAttribute("sheet-key", `${this.sheetKey}`), element.classList.add("vtable-sheet"), 
        element.style.outline = "none", element.style.position = "relative";
        const width = this.container.clientWidth || 800, height = this.container.clientHeight || 600;
        return element.style.width = `${width}px`, element.style.height = `${height}px`, 
        element;
    }
    _initializeTable() {
        const tableOptions = this._generateTableOptions();
        this.tableInstance = new vtable_1.ListTable(tableOptions), this.element.classList.add("vtable-excel-cursor"), 
        this.eventBus = this.tableInstance.eventBus;
    }
    _generateTableOptions() {
        var _a;
        let isShowTableHeader = this.options.showHeader;
        if (this.options.columns) for (let i = 0; i < this.options.columns.length; i++) this.options.columns[i].field = i, 
        this.options.columns[i].key = i; else isShowTableHeader = !!(0, vutils_1.isValid)(isShowTableHeader) && isShowTableHeader, 
        this.options.columns = [];
        if (this.options.data) {
            if (0 === this.options.columns.length && this.options.firstRowAsHeader) {
                const data = this.options.data;
                if (data && data.length > 0) for (let i = 0; i < data[0].length; i++) this.options.columns[i] = {
                    field: i,
                    key: i,
                    title: data[0][i],
                    filter: !!this.options.filter
                };
                data.shift(), isShowTableHeader = !0;
            }
        } else this.options.data = [];
        const keyboardOptions = Object.assign(Object.assign({}, this.options.keyboardOptions), {
            copySelected: !0,
            pasteValueToCell: !0,
            showCopyCellBorder: !0,
            cutSelected: !0
        });
        let changedTheme;
        if ((null === (_a = this.options) || void 0 === _a ? void 0 : _a.theme) || (this.options.theme = ts_types_2.VTableThemes.DEFAULT), 
        this.options.theme = this.options.theme, this.options.theme.bodyStyle && !(0, tools_1.isPropertyWritable)(this.options.theme, "bodyStyle")) {
            changedTheme = this.options.theme.extends(this.options.theme.getExtendTheme());
            const extendThemeOption = changedTheme.getExtendTheme();
            extendThemeOption.frameStyle = Object.assign({}, extendThemeOption.frameStyle, {
                shadowBlur: 0,
                cornerRadius: 0,
                borderLineWidth: 0
            });
        } else "string" == typeof this.options.theme || (changedTheme = this.options.theme, 
        changedTheme.frameStyle = Object.assign({}, this.options.theme.frameStyle, {
            shadowBlur: 0,
            cornerRadius: 0,
            borderLineWidth: 0
        }));
        return Object.assign(Object.assign({}, this.options), {
            dragOrder: {
                maintainArrayDataOrder: !0
            },
            addRecordRule: "Array",
            defaultCursor: "cell",
            records: this.options.data,
            sortState: this.options.sortState,
            container: this.element,
            showHeader: isShowTableHeader,
            keyboardOptions: keyboardOptions,
            theme: changedTheme,
            excelOptions: {
                fillHandle: !0
            },
            customConfig: {
                selectCellWhenCellEditorNotExists: !0
            }
        });
    }
    _setupEventListeners() {
        this.tableInstance && (this.tableInstance.on("mousedown_cell", (event => {
            this.vtableSheet.formulaManager.formulaWorkingOnCell && event.event.preventDefault();
        })), this.tableInstance.on("selected_changed", (event => {
            this.tableInstance.eventManager.isDraging || (this.vtableSheet.formulaManager.formulaWorkingOnCell || (this.editingCell = {
                sheet: this.getKey(),
                row: event.row,
                col: event.col
            }), this.handleCellSelected(event)), this.handleSelectionChanged(event);
        })), this.tableInstance.on("drag_select_end", (event => {
            this.handleDragSelectEnd(event);
        })), this.tableInstance.on("change_cell_value", (event => {
            this.handleCellValueChanged(event);
        })), this.tableInstance.on("add_record", (event => {
            this.handleDataRecordsChanged("add", event);
        })), this.tableInstance.on("delete_record", (event => {
            this.handleDataRecordsChanged("delete", event);
        })), this.tableInstance.on("add_column", (event => {
            this.handleColumnsChanged("add", event);
        })), this.tableInstance.on("delete_column", (event => {
            this.handleColumnsChanged("delete", event);
        })), this.tableInstance.on("click_cell", (() => {
            this.element.classList.add("vtable-excel-cursor");
        })), this.tableInstance.on("change_header_position", (event => {
            this.handleChangeHeaderPosition(event);
        })));
    }
    handleCellSelected(event) {
        this.selection = {
            startRow: event.row,
            startCol: event.col,
            endRow: event.row,
            endCol: event.col
        };
        const cellSelectedEvent = {
            row: event.row,
            col: event.col,
            value: event.value,
            cellElement: event.cellElement,
            originalEvent: event.originalEvent
        };
        this.fire(ts_types_1.WorkSheetEventType.CELL_CLICK, cellSelectedEvent);
    }
    handleSelectionChanged(event) {
        var _a;
        if (null === (_a = null == event ? void 0 : event.ranges) || void 0 === _a ? void 0 : _a.length) {
            const r = event.ranges[event.ranges.length - 1];
            this.selection = {
                startRow: r.start.row,
                startCol: r.start.col,
                endRow: r.end.row,
                endCol: r.end.col
            };
        }
        const selectionChangedEvent = {
            row: event.row,
            col: event.col,
            ranges: event.ranges,
            cells: event.cells,
            originalEvent: event.originalEvent
        };
        this.fire(ts_types_1.WorkSheetEventType.SELECTION_CHANGED, selectionChangedEvent);
    }
    handleDragSelectEnd(event) {
        var _a;
        if (null === (_a = null == event ? void 0 : event.cells) || void 0 === _a ? void 0 : _a.length) {
            const first = event.cells[0][0], lastRow = event.cells[event.cells.length - 1], last = lastRow[lastRow.length - 1];
            this.selection = {
                startRow: first.row,
                startCol: first.col,
                endRow: last.row,
                endCol: last.col
            };
        }
        const selectionEndEvent = {
            row: event.row,
            col: event.col,
            ranges: event.ranges,
            cells: event.cells,
            originalEvent: event.originalEvent
        };
        this.fire(ts_types_1.WorkSheetEventType.SELECTION_END, selectionEndEvent);
    }
    handleCellValueChanged(event) {
        const cellValueChangedEvent = {
            row: event.row,
            col: event.col,
            oldValue: event.rawValue,
            newValue: event.changedValue
        };
        this.fire(ts_types_1.WorkSheetEventType.CELL_VALUE_CHANGED, cellValueChangedEvent);
    }
    handleDataRecordsChanged(type, event) {
        try {
            const sheetKey = this.getKey(), normalizedData = this.vtableSheet.formulaManager.normalizeSheetData(this.tableInstance.records, this.tableInstance);
            if (this.vtableSheet.formulaManager.formulaEngine.updateSheetData(sheetKey, normalizedData), 
            "add" === type) {
                const {recordIndex: recordIndex, recordCount: recordCount} = event;
                if (void 0 !== recordIndex && recordCount > 0) this.vtableSheet.formulaManager.addRows(sheetKey, recordIndex, recordCount); else {
                    const currentRowCount = this.getRowCount();
                    this.vtableSheet.formulaManager.addRows(sheetKey, currentRowCount, recordCount);
                }
            } else if ("delete" === type) {
                const {rowIndexs: rowIndexs, deletedCount: deletedCount} = event;
                if (rowIndexs && rowIndexs.length > 0) {
                    const minIndex = Math.min(...rowIndexs.flat());
                    this.vtableSheet.formulaManager.removeRows(sheetKey, minIndex, deletedCount);
                }
            }
        } catch (error) {}
    }
    handleColumnsChanged(type, event) {
        try {
            const sheetKey = this.getKey(), normalizedData = this.vtableSheet.formulaManager.normalizeSheetData(this.tableInstance.records, this.tableInstance);
            if (this.vtableSheet.formulaManager.formulaEngine.updateSheetData(sheetKey, normalizedData), 
            "add" === type) {
                const {columnIndex: columnIndex, columnCount: columnCount} = event;
                if (void 0 !== columnIndex && columnCount > 0) this.vtableSheet.formulaManager.addColumns(sheetKey, columnIndex, columnCount); else {
                    const currentColumnCount = this.getColumnCount();
                    this.vtableSheet.formulaManager.addColumns(sheetKey, currentColumnCount, columnCount);
                }
            } else if ("delete" === type) {
                const {deleteColIndexs: deleteColIndexs} = event;
                if (deleteColIndexs && deleteColIndexs.length > 0) {
                    const minIndex = Math.min(...deleteColIndexs.flat()), deletedCount = deleteColIndexs.length;
                    this.vtableSheet.formulaManager.removeColumns(sheetKey, minIndex, deletedCount);
                }
            }
        } catch (error) {}
    }
    handleChangeHeaderPosition(event) {
        "column" === event.movingColumnOrRow ? this.handleChangeColumnHeaderPosition(event) : this.handleChangeRowHeaderPosition(event);
    }
    handleChangeColumnHeaderPosition(event) {
        const {source: source, target: target} = event, {col: sourceCol, row: sourceRow} = source, {col: targetCol, row: targetRow} = target, sheetKey = this.getKey(), normalizedData = this.vtableSheet.formulaManager.normalizeSheetData(this.tableInstance.records, this.tableInstance);
        this.vtableSheet.formulaManager.formulaEngine.updateSheetData(sheetKey, normalizedData), 
        this.vtableSheet.formulaManager.changeColumnHeaderPosition(sheetKey, sourceCol, targetCol);
    }
    handleChangeRowHeaderPosition(event) {
        const {source: source, target: target} = event, {row: sourceRow} = source, {row: targetRow} = target, sheetKey = this.getKey(), normalizedData = this.vtableSheet.formulaManager.normalizeSheetData(this.tableInstance.records, this.tableInstance);
        this.vtableSheet.formulaManager.formulaEngine.updateSheetData(sheetKey, normalizedData), 
        this.vtableSheet.formulaManager.changeRowHeaderPosition(sheetKey, sourceRow, targetRow);
    }
    fireEvent(eventName, eventData) {
        this.fire(eventName, eventData);
    }
    on(eventName, handler) {
        return super.on(eventName, handler);
    }
    resize() {
        this.element && (null !== this.resizeTimer && (window.clearTimeout(this.resizeTimer), 
        this.resizeTimer = null), this.isResizing ? this.resizeTimer = window.setTimeout((() => {
            this.doResize(), this.resizeTimer = null;
        }), 50) : this.doResize());
    }
    doResize() {
        try {
            this.isResizing = !0;
            const width = this.container.clientWidth || 800, height = this.container.clientHeight || 600;
            parseInt(this.element.style.width, 10) === width && parseInt(this.element.style.height, 10) === height || (this.element.style.width = `${width}px`, 
            this.element.style.height = `${height}px`, this.tableInstance && this.tableInstance.resize());
        } catch (error) {} finally {
            this.isResizing = !1;
        }
    }
    getElement() {
        return this.element;
    }
    getContainer() {
        return this.container;
    }
    getKey() {
        return this.sheetKey;
    }
    getTitle() {
        return this.sheetTitle;
    }
    setTitle(title) {
        this.sheetTitle = title, this.options.sheetTitle = title;
    }
    getColumns() {
        return this.tableInstance.columns || [];
    }
    getData() {
        return this.options.data || [];
    }
    getCopiedData() {
        return this.getData().map((row => Array.isArray(row) ? row.slice() : []));
    }
    getCellValue(row, col) {
        if (this.tableInstance) try {
            return this.tableInstance.getCellValue(col, row);
        } catch (error) {}
        const data = this.getData();
        return data && data[row] && void 0 !== data[row][col] ? data[row][col] : null;
    }
    setCellValue(row, col, value) {
        const data = this.getData();
        if (data && data[row]) {
            const oldValue = data[row][col];
            data[row][col] = value, this.tableInstance && this.tableInstance.changeCellValue(col, row, value);
            const event = {
                row: row,
                col: col,
                oldValue: oldValue,
                newValue: value
            };
            this.fire("cellValueChanged", event);
        }
    }
    getCellByAddress(address) {
        const coord = this.coordFromAddress(address);
        return {
            coord: coord,
            value: this.getCellValue(coord.row, coord.col)
        };
    }
    addressFromCoord(coordOrRow, col) {
        let row, colNum;
        "object" == typeof coordOrRow ? (row = coordOrRow.row, colNum = coordOrRow.col) : (row = coordOrRow, 
        colNum = col);
        let colStr = "", tempCol = colNum + 1;
        do {
            tempCol -= 1, colStr = String.fromCharCode(65 + tempCol % 26) + colStr, tempCol = Math.floor(tempCol / 26);
        } while (tempCol > 0);
        return `${colStr}${row + 1}`;
    }
    coordFromAddress(address) {
        const match = address.match(/^([A-Z]+)([0-9]+)$/);
        if (!match) throw new Error(`Invalid cell address: ${address}`);
        const colStr = match[1], rowStr = match[2];
        let col = 0;
        for (let i = 0; i < colStr.length; i++) col = 26 * col + (colStr.charCodeAt(i) - 64);
        return {
            row: parseInt(rowStr, 10) - 1,
            col: col - 1
        };
    }
    getSelection() {
        return this.selection;
    }
    getMultipleSelections() {
        if (!this.tableInstance) return this.selection ? [ this.selection ] : [];
        const vtableRanges = this.tableInstance.getSelectedCellRanges();
        return 0 === vtableRanges.length ? this.selection ? [ this.selection ] : [] : vtableRanges.map((range => ({
            startRow: range.start.row,
            startCol: range.start.col,
            endRow: range.end.row,
            endCol: range.end.col
        })));
    }
    setFirstRowAsHeader() {
        const data = this.getData();
        if (data && data.length > 0) for (let i = 0; i < data[0].length; i++) this.options.columns[i] ? (this.options.columns[i].title = data[0][i], 
        this.options.columns[i].field = i) : this.options.columns[i] = {
            field: i,
            title: data[0][i]
        };
        data.shift(), this.tableInstance.updateOption(Object.assign(Object.assign({}, this.options), {
            columns: this.options.columns,
            showHeader: !0,
            records: data
        }));
    }
    release() {
        var _a;
        this.tableInstance && this.tableInstance.release(), this.element && this.element.parentNode && this.element.parentNode.removeChild(this.element), 
        null === (_a = this.tableInstance) || void 0 === _a || _a.release();
    }
}

exports.WorkSheet = WorkSheet;
//# sourceMappingURL=WorkSheet.js.map