import { ApiBase } from './ApiBase';
import { HighlightCellAdd, HighlightCellDelete, HighlightCellDeleteAll, HighlightColumnAdd, HighlightColumnDelete, HighlightColumnDeleteAll, HighlightRowAdd, HighlightRowDelete, GridHighlightRowDeleteAll, HighlightRowsAdd, GridHighlightRowsDelete, } from '../../Redux/ActionsReducers/InternalRedux';
import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants';
import { GridInternalApi } from '../Internal/GridInternalApi';
import ArrayExtensions from '../../Utilities/Extensions/ArrayExtensions';
import { WINDOW_SHOW_TRANSPOSED_VIEW } from '../../View/Components/Popups/WindowPopups/windowFactory';
import { ROW_SUMMARY_ROW_ID } from '../../AdaptableState/Common/RowSummary';
import { errorOnce } from '../../agGrid/AdaptableLogger';
export class GridApiImpl extends ApiBase {
    internalApi;
    constructor(_adaptable) {
        super(_adaptable);
        this.internalApi = new GridInternalApi(_adaptable);
    }
    getAgGridColumnDefs() {
        return this._adaptable.agGridAdapter.getAgGridApi().getColumnDefs();
    }
    getVariant() {
        return this.getAdaptableVariant();
    }
    getInternalState() {
        return this.getAdaptableState().Internal;
    }
    loadGridData(dataSource) {
        // we intentionally set an initial empty array,
        // to prevent `cellchanged` events from being triggered for rows that have
        // the same primary key with existing rows
        // see #testprevent_cellchanged_event_on_load_grid_data
        this._adaptable.agGridAdapter.setGridOption('rowData', []);
        this._adaptable.setGridData(dataSource);
        const allRowNodes = this.getAllRowNodes();
        const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataSource, allRowNodes, 'Load');
        this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
    }
    getGridData() {
        return this._adaptable.getGridData();
    }
    getFilteredData() {
        return this._adaptable.getFilteredData();
    }
    getVisibleData() {
        const data = [];
        this.getAdaptableInternalApi().forAllVisibleRowNodesDo((rowNode) => {
            if (!this.isGroupRowNode(rowNode)) {
                data.push(rowNode.data);
            }
        });
        return data;
    }
    async updateGridData(dataRows, dataUpdateConfig) {
        const rowNodes = await this._adaptable.updateRows(dataRows, dataUpdateConfig);
        const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows, rowNodes, 'Update');
        this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        return rowNodes;
    }
    async addOrUpdateGridData(dataRows, dataUpdateConfig) {
        const { added, updated } = await this._adaptable.addOrUpdateRows(dataRows, dataUpdateConfig);
        if (ArrayExtensions.IsNotNullOrEmpty(updated)) {
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows, updated, 'Update');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        }
        if (ArrayExtensions.IsNotNullOrEmpty(added)) {
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows, added, 'Add');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        }
        return {
            addedRows: added,
            updatedRows: updated,
        };
    }
    async addGridData(dataRows, dataUpdateConfig) {
        const rowNodes = await this._adaptable.addRows(dataRows, dataUpdateConfig);
        const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows, rowNodes, 'Add');
        this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        return rowNodes;
    }
    undoCellEdit(cellDataChangedInfo) {
        // for the reason of this hacky solution see the comments in DataService
        this.getAdaptableInternalApi().getDataService().logUndoChange(cellDataChangedInfo);
        const cellUpdateRequest = {
            columnId: cellDataChangedInfo.column.columnId,
            newValue: cellDataChangedInfo.oldValue, // need old value as we are undoing
            primaryKeyValue: cellDataChangedInfo.primaryKeyValue,
            rowNode: cellDataChangedInfo.rowNode,
        };
        this.setCellValue(cellUpdateRequest);
        return true;
    }
    async deleteGridData(dataRows, dataUpdateConfig) {
        if (this.checkArrayExists(dataRows)) {
            const rowNodes = await this._adaptable.deleteRows(dataRows, dataUpdateConfig);
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows, rowNodes, 'Delete');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
            return rowNodes;
        }
        return [];
    }
    async manageGridData(dataRows, config) {
        const transactionResult = await this._adaptable.manageGridRows(dataRows, config);
        if (Array.isArray(transactionResult.removedRows) && transactionResult.removedRows.length) {
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.delete, transactionResult.removedRows, 'Delete');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        }
        if (Array.isArray(transactionResult.updatedRows) && transactionResult.updatedRows.length) {
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.update, transactionResult.updatedRows, 'Update');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        }
        if (Array.isArray(transactionResult.addedRows) && transactionResult.addedRows.length) {
            const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.add, transactionResult.addedRows, 'Add');
            this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
        }
        return transactionResult;
    }
    setCellValue(cellUpdateRequest) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(cellUpdateRequest.columnId);
        if (!abColumn) {
            this.logWarn(`setCellValue() - column not found for columnId: ${cellUpdateRequest.columnId}`);
            return;
        }
        const rowNode = cellUpdateRequest.rowNode ?? this.getRowNodeForPrimaryKey(cellUpdateRequest.primaryKeyValue);
        if (!rowNode) {
            this.logWarn(`setCellValue() - rowNode not found for primaryKeyValue: ${cellUpdateRequest.primaryKeyValue}`);
            return;
        }
        this._adaptable.setDataValue(cellUpdateRequest.newValue, abColumn, cellUpdateRequest.primaryKeyValue, rowNode);
        this.refreshCell(rowNode, abColumn.columnId);
    }
    setCellValues(cellUpdateRequests) {
        cellUpdateRequests?.forEach((cellUpdateRequest) => this.setCellValue(cellUpdateRequest));
    }
    getCellSummaryInfo() {
        return this.getAdaptableState().Internal.CellSummary.CellSummaryInfo;
    }
    getSelectedCellInfo() {
        return this.getInternalState().SelectedCellInfo;
    }
    getSelectedRowInfo() {
        return this.getInternalState().SelectedRowInfo ?? { gridRows: [] };
    }
    getCellDisplayValue(primaryKeyValue, columnId) {
        const rowNode = this.getRowNodeForPrimaryKey(primaryKeyValue);
        return rowNode ? this.getDisplayValueFromRowNode(rowNode, columnId) : undefined;
    }
    getCellRawValue(primaryKeyValue, columnId) {
        const rowNode = this.getRowNodeForPrimaryKey(primaryKeyValue);
        return rowNode ? this.getRawValueFromRowNode(rowNode, columnId) : undefined;
    }
    getCellNormalisedValue(primaryKeyValue, columnId) {
        const rowNode = this.getRowNodeForPrimaryKey(primaryKeyValue);
        return rowNode ? this.getNormalisedValueFromRowNode(rowNode, columnId) : undefined;
    }
    applyFiltering() {
        this._adaptable.applyFiltering();
    }
    clearFiltering() {
        // slightly round the houses but we have to call ColumnFilterAPI as it does it properly
        this.getColumnFilterApi().clearColumnFilters();
    }
    getColumnSorts() {
        return this.getLayoutApi().getCurrentLayout().ColumnSorts;
    }
    getColumnSortForColumn(columnId) {
        let columnSorts = this.getColumnSorts();
        return columnSorts?.find((cs) => cs.ColumnId == columnId);
    }
    setAdaptableSorting(columnSorts) {
        this._adaptable.setColumnSort(columnSorts);
    }
    clearAdaptableSorting() {
        this._adaptable.clearColumnSort();
    }
    selectRow(primaryKeyValue, clearSelection) {
        this.selectNode(this.getRowNodeForPrimaryKey(primaryKeyValue), clearSelection);
    }
    selectRows(primaryKeyValues, clearSelection) {
        let nodes = [];
        primaryKeyValues.forEach((pkValue) => {
            nodes.push(this.getRowNodeForPrimaryKey(pkValue));
        });
        this.selectNodes(nodes, clearSelection);
    }
    selectNode(rowNode, clearSelection) {
        this._adaptable.selectNode(rowNode, clearSelection);
    }
    selectNodes(rowNodes, clearSelection) {
        this._adaptable.selectNodes(rowNodes, clearSelection);
    }
    deSelectRow(primaryKeyValue, clearSelection) {
        this._adaptable.deSelectNode(this.getRowNodeForPrimaryKey(primaryKeyValue), clearSelection);
    }
    deSelectRows(primaryKeyValues, clearSelection) {
        let nodes = [];
        primaryKeyValues.forEach((pkValue) => {
            nodes.push(this.getRowNodeForPrimaryKey(pkValue));
        });
        this.deSelectNodes(nodes, clearSelection);
    }
    deSelectNode(rowNode, clearSelection) {
        this._adaptable.deSelectNode(rowNode, clearSelection);
    }
    deSelectNodes(rowNodes, clearSelection) {
        this._adaptable.deSelectNodes(rowNodes, clearSelection);
    }
    getSelectionStartEndNodes(gridCellRange) {
        let startNode;
        let endNode;
        startNode = gridCellRange.primaryKeyValueEnd
            ? this._adaptable.getRowNodeForPrimaryKey(gridCellRange.primaryKeyValueStart)
            : this._adaptable.getRowNodeByIndex(gridCellRange.rowIndexStart);
        if (gridCellRange.primaryKeyValueEnd) {
            endNode = this._adaptable.getRowNodeForPrimaryKey(gridCellRange.primaryKeyValueEnd);
        }
        else if (gridCellRange.rowIndexEnd) {
            endNode = this._adaptable.getRowNodeByIndex(gridCellRange.rowIndexEnd);
        }
        else {
            endNode = startNode;
        }
        return [startNode, endNode];
    }
    selectCellRange(gridCellRange, clearSelection) {
        if (gridCellRange == undefined) {
            return;
        }
        if (gridCellRange.primaryKeyValueStart == undefined &&
            gridCellRange.rowIndexStart == undefined) {
            return;
        }
        const [startNode, endNode] = this.getSelectionStartEndNodes(gridCellRange);
        if (startNode && endNode) {
            this._adaptable.selectCells(gridCellRange.columnIds, startNode, endNode, clearSelection);
        }
    }
    selectCellRangeByQuery(query, gridCellRange, clearSelection) {
        const filteredRowNodes = [];
        const isRowNodeInQuery = (rowNode) => {
            try {
                return this.getAdaptableApi()
                    .internalApi.getQueryLanguageService()
                    .evaluateBooleanExpression(query, 'GridInfo', rowNode);
            }
            catch (error) {
                errorOnce(error.message);
                return false;
            }
        };
        if (gridCellRange) {
            const [startNode, endNode] = this.getSelectionStartEndNodes(gridCellRange);
            for (let rowIndex = startNode.rowIndex; rowIndex <= endNode.rowIndex; rowIndex++) {
                const rowNode = this._adaptable.getRowNodeByIndex(rowIndex);
                isRowNodeInQuery(rowNode) && filteredRowNodes.push(rowNode);
            }
        }
        else {
            // include all row
            this._adaptable.forAllRowNodesDo((rowNode) => {
                isRowNodeInQuery(rowNode) && filteredRowNodes.push(rowNode);
            });
        }
        if (!filteredRowNodes.length) {
            return;
        }
        let preapredGridCellRange = gridCellRange;
        if (!preapredGridCellRange) {
            /**
             * Select all rows and all columns
             */
            const currentLayout = this.getLayoutApi().getCurrentLayout();
            preapredGridCellRange = {
                columnIds: currentLayout.TableColumns,
            };
        }
        // ranges of row with consecutive indexes
        const rowRanges = filteredRowNodes.reduce((acc, rowNode, index, collection) => {
            // add start if there is none
            const prevRange = acc[acc.length - 1];
            if (prevRange.startNode === undefined) {
                prevRange.startNode = rowNode;
            }
            // add end if next is not consecutive
            const nextNode = collection[index + 1];
            if (nextNode && nextNode.rowIndex - 1 !== rowNode.rowIndex) {
                prevRange.endNode = rowNode;
                // start a new one
                acc.push({});
            }
            // if at the end close last range
            if (index === collection.length - 1) {
                prevRange.endNode = rowNode;
            }
            return acc;
        }, [{}]);
        let preparedClearSelection = clearSelection;
        rowRanges.forEach((range) => {
            // clear only on first range selection
            this._adaptable.selectCells(preapredGridCellRange.columnIds, range.startNode, range.endNode, preparedClearSelection);
            preparedClearSelection = false;
        });
    }
    selectColumn(columnId) {
        this.selectColumns([columnId]);
    }
    selectColumns(columnIds) {
        this.getColumnApi().selectColumns(columnIds);
    }
    getFirstRowNode() {
        return this._adaptable.getFirstRowNode();
    }
    getFirstDisplayedRowNode() {
        return this._adaptable.getFirstDisplayedRowNode();
    }
    getVisibleRowNodes(config) {
        const rowNodes = [];
        this.getAdaptableInternalApi().forAllVisibleRowNodesDo((rowNode) => rowNodes.push(rowNode), config);
        return rowNodes;
    }
    getAllRowNodes(config) {
        return this._adaptable.getAllRowNodes(config);
    }
    getGroupRowNodes(config) {
        return this._adaptable.getGroupRowNodes(config);
    }
    getGridCellFromRowNode(rowNode, columnId) {
        return this._adaptable.getGridCellFromRowNode(rowNode, columnId);
    }
    getRawValueFromRowNode(rowNode, columnId) {
        return this._adaptable.getRawValueFromRowNode(rowNode, columnId);
    }
    getDisplayValueFromRowNode(rowNode, columnId) {
        return this._adaptable.getDisplayValueFromRowNode(rowNode, columnId);
    }
    getDisplayValueFromRawValue(rowNode, columnId, rawValue) {
        return this._adaptable.getDisplayValueFromRawValue(rowNode, columnId, rawValue);
    }
    getNormalisedValueFromRowNode(rowNode, columnId) {
        const rawValue = this._adaptable.getRawValueFromRowNode(rowNode, columnId);
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        return this._adaptable.getNormalisedValueFromRawValue(rawValue, abColumn);
    }
    getRowNodesForPrimaryKeys(primaryKeyValues) {
        return this._adaptable.getRowNodesForPrimaryKeys(primaryKeyValues);
    }
    getRowNodeForPrimaryKey(primaryKeyValue) {
        return this._adaptable.getRowNodeForPrimaryKey(primaryKeyValue);
    }
    getPrimaryKeyValueForRowNode(rowNode) {
        return this._adaptable.getPrimaryKeyValueFromRowNode(rowNode);
    }
    getRowNodeForIndex(index) {
        return this._adaptable.getRowNodeByIndex(index);
    }
    getPrimaryKeyValuesForRowNodes(rowNodes) {
        return rowNodes.map((rowNode) => this.getPrimaryKeyValueForRowNode(rowNode));
    }
    setRowGroupColumns(columnIds) {
        this._adaptable.setRowGroupColumns(columnIds);
    }
    clearRowGroupColumns() {
        this._adaptable.clearRowGroupColumns();
    }
    expandAllRowGroups() {
        this._adaptable.expandAllRowGroups();
    }
    collapseAllRowGroups() {
        this._adaptable.collapseAllRowGroups();
    }
    expandRowGroupsForValues(columnValues) {
        this._adaptable.expandRowGroupsForValues(columnValues);
    }
    isGridPivotable() {
        return !this.isTreeDataGrid();
    }
    isGridGroupable() {
        return !this.isTreeDataGrid();
    }
    isGridRowSelectable() {
        return this._adaptable.isGridRowSelectable();
    }
    isGridRowSelected(primaryKeyValue) {
        const rowInfo = this.getSelectedRowInfo();
        const row = rowInfo.gridRows.find((gr) => gr.primaryKeyValue == primaryKeyValue);
        return row != undefined;
    }
    isGridRangeSelectable() {
        return this._adaptable.isGridRangeSelectable();
    }
    isGridRowGrouped() {
        return this._adaptable.isGridGroupingActive();
    }
    isGridInPivotMode() {
        return this.getLayoutApi().isCurrentLayoutPivot();
    }
    isMasterDetailGrid() {
        return this.getAgGridApi().getGridOption('masterDetail');
    }
    isTreeDataGrid() {
        return this.getAgGridApi().getGridOption('treeData');
    }
    isGroupRowNode(rowNode) {
        return this._adaptable.isGroupRowNode(rowNode);
    }
    isGrandTotalRowNode(rowNode) {
        return this._adaptable.isGrandTotalRowNode(rowNode);
    }
    isVisibleRowNode(rowNode) {
        return this._adaptable.isRowNodeVisible(rowNode);
    }
    isSummaryNode(rowNode) {
        return !!rowNode?.data?.[ROW_SUMMARY_ROW_ID];
    }
    isQuickFilterAvailable() {
        return this._adaptable.isQuickFilterAvailable();
    }
    redrawGrid() {
        this._adaptable.redrawBody();
        this._adaptable.refreshHeader();
    }
    getGridCellsForRawValue(columnId, rawValue) {
        const gridCells = this._adaptable.getGridCellsForColumn(columnId);
        if (!gridCells) {
            return undefined;
        }
        const returnValues = [];
        gridCells.forEach((gc) => {
            if (gc.rawValue === rawValue) {
                returnValues.push(gc);
            }
        });
        return returnValues;
    }
    getCellRawValueCount(columnId, rawValue) {
        const gridCells = this.getGridCellsForRawValue(columnId, rawValue);
        return gridCells?.length;
    }
    getGridCellsForDisplayValue(columnId, displayValue) {
        const gridCells = this._adaptable.getGridCellsForColumn(columnId);
        if (!gridCells) {
            return undefined;
        }
        const returnGridCells = [];
        gridCells.forEach((gc) => {
            if (gc.displayValue === displayValue) {
                returnGridCells.push(gc);
            }
        });
        return returnGridCells;
    }
    jumpToRow(primaryKeyValue) {
        const node = this._adaptable.getRowNodeForPrimaryKey(primaryKeyValue);
        this._adaptable.jumpToRow(node);
    }
    jumpToColumn(columnId) {
        this._adaptable.jumpToColumn(columnId);
    }
    jumpToCell(primaryKeyValue, columnId, rowNode) {
        const node = rowNode ?? this._adaptable.getRowNodeForPrimaryKey(primaryKeyValue);
        this._adaptable.jumpToCell(columnId, node);
    }
    highlightCell(cellHighlightInfo) {
        this.dispatchAction(HighlightCellAdd(cellHighlightInfo));
        if (cellHighlightInfo.timeout) {
            setTimeout(() => {
                this.unHighlightCell(cellHighlightInfo.primaryKeyValue, cellHighlightInfo.columnId);
            }, cellHighlightInfo.timeout);
        }
    }
    unHighlightCell(primaryKeyValue, columnId) {
        this.dispatchAction(HighlightCellDelete(primaryKeyValue, columnId));
    }
    unHighlightAllCells() {
        this.dispatchAction(HighlightCellDeleteAll());
    }
    highlightColumn(columnHighlightInfo) {
        this.dispatchAction(HighlightColumnAdd(columnHighlightInfo));
        if (columnHighlightInfo.timeout) {
            setTimeout(() => {
                this.unHighlightColumn(columnHighlightInfo.columnId);
            }, columnHighlightInfo.timeout);
        }
    }
    unHighlightColumn(columnId) {
        this.dispatchAction(HighlightColumnDelete(columnId));
    }
    unHighlightAllColumns() {
        this.dispatchAction(HighlightColumnDeleteAll());
    }
    highlightRow(rowHighlightInfo) {
        this.dispatchAction(HighlightRowAdd(rowHighlightInfo));
        if (rowHighlightInfo.timeout) {
            setTimeout(() => {
                this.unHighlightRow(rowHighlightInfo.primaryKeyValue);
            }, rowHighlightInfo.timeout);
        }
    }
    highlightRows(rowHighlightInfos) {
        this.dispatchAction(HighlightRowsAdd(rowHighlightInfos));
        if (rowHighlightInfos.timeout) {
            setTimeout(() => {
                this.unHighlightRows(rowHighlightInfos.primaryKeyValues);
            }, rowHighlightInfos.timeout);
        }
    }
    unHighlightRow(primaryKeyValue) {
        this.dispatchAction(HighlightRowDelete(primaryKeyValue));
    }
    unHighlightRows(primaryKeyValues) {
        this.dispatchAction(GridHighlightRowsDelete(primaryKeyValues));
    }
    unHighlightAllRows() {
        this.dispatchAction(GridHighlightRowDeleteAll());
    }
    refreshCell(rowNode, columnId, suppressFlash = true) {
        this._adaptable.refreshCell(rowNode, columnId, suppressFlash);
    }
    refreshCells(rowNode, columnIds, suppressFlash = true) {
        this._adaptable.refreshCells(rowNode, columnIds, suppressFlash);
    }
    refreshAllCells(forceUpdate = false) {
        this._adaptable.refreshAllCells(forceUpdate);
    }
    refreshGridCell(gridCell) {
        this.refreshCell(gridCell.rowNode, gridCell.column.columnId);
    }
    refreshGridCells(gridCells) {
        gridCells.forEach((gc) => {
            this.refreshGridCell(gc);
        });
    }
    refreshColumn(columnId) {
        this._adaptable.refreshColumns([columnId], true);
    }
    refreshColumns(columnIds) {
        this._adaptable.refreshColumns(columnIds, true);
    }
    refreshRowByPrimaryKey(primaryKey) {
        const rowNode = this.getRowNodeForPrimaryKey(primaryKey);
        this.refreshRowNode(rowNode);
    }
    refreshRowNode(rowNode) {
        this._adaptable.redrawRow(rowNode);
    }
    refreshRowNodes(rowNodes) {
        this._adaptable.redrawRows(rowNodes);
    }
    refreshGroupRowNodes() {
        // see https://www.ag-grid.com/javascript-data-grid/client-side-row-stages/#refreshing-the-client-side-model
        this.getAgGridApi().refreshClientSideRowModel('group');
        this._adaptable.updateRowGroupsAndColumnGroupsExpandedState();
    }
    isCellEditable(gridCell) {
        // If not Grid Cell or Column then return false - GridCell.column may be undefined for cells from synthetic columns created by AG Grid (ex. autoGroup columns)
        if (!gridCell || !gridCell.column || !gridCell.rowNode) {
            return false;
        }
        if (gridCell.rowNode && this.isSummaryNode(gridCell.rowNode)) {
            return false;
        }
        const agGridColumn = this.getColumnApi().internalApi.getAgGridColumnForAdaptableColumn(gridCell.column.columnId);
        // this will invoke the colDef.editable callback where we check both AdapTable and AG Grid editability
        return agGridColumn?.isCellEditable(gridCell.rowNode);
    }
    isCellEdited(gridCell) {
        if (!gridCell) {
            return false;
        }
        const cellDataChangedInfo = this.getDataChangeHistoryApi().getDataChangeForGridCell(gridCell);
        return cellDataChangedInfo != null;
    }
    isEveryCellEditable(gridCells) {
        for (let gridCell of gridCells) {
            if (!this.isCellEditable(gridCell)) {
                return false;
            }
        }
        return true;
    }
    getRowCount() {
        return this._adaptable.getRowCount();
    }
    getVisibleRowCount() {
        return this._adaptable.getVisibleRowCount();
    }
    getRowsInViewport() {
        return this._adaptable.getRowsInViewport();
    }
    getColumnCount() {
        return this._adaptable.getColumnCount();
    }
    getVisibleColumnCount() {
        return this._adaptable.getVisibleColumnCount();
    }
    selectAll() {
        this._adaptable.selectAll();
    }
    deselectAll() {
        this._adaptable.deselectAll();
    }
    getGridContainerElement() {
        return this._adaptable.getAgGridContainerElement();
    }
    openGridInfoSettingsPanel() {
        this.showModulePopup(ModuleConstants.GridInfoModuleId);
    }
    getAgGridRowModelType() {
        return this._adaptable.getAgGridRowModelType();
    }
    showTransposedView(transposeConfig = {}) {
        const transposedColumnId = transposeConfig.transposedColumnId ?? this.getOptionsApi().getPrimaryKey();
        const hideTransposedColumn = transposeConfig.hideTransposedColumn ?? true;
        const visibleColumns = transposeConfig.visibleColumns ?? false;
        const visibleRows = transposeConfig.visibleRows ?? false;
        const autosize = transposeConfig.autosize ?? true;
        this.getAdaptableInternalApi().showPopupWindow({
            id: WINDOW_SHOW_TRANSPOSED_VIEW,
            factoryId: WINDOW_SHOW_TRANSPOSED_VIEW,
            title: 'Transposed View',
            icon: 'grid',
            popupProps: {
                transposedColumnId,
                hideTransposedColumn,
                visibleColumns,
                visibleRows,
                autosize,
            },
        });
    }
    getAllAgGridColumns() {
        return this._adaptable.getAllGridColumns();
    }
    updateAgGridColumnState(columnState) {
        const columnExists = this.getColumnApi().doesColumnExist(columnState.colId);
        if (!columnExists) {
            this.logWarn(`Column with id ${columnState.colId} does not exist, could NOT update configuration`);
            return;
        }
        const agGridApi = this._adaptable.agGridAdapter.getAgGridApi();
        agGridApi.applyColumnState({
            state: [columnState],
        });
    }
    updateAgGridColumnStates(columnStates) {
        const existingColumnStates = columnStates.filter((cc) => this.getColumnApi().doesColumnExist(cc.colId));
        const notExistingColumnIds = columnStates
            .filter((cc) => !this.getColumnApi().doesColumnExist(cc.colId))
            .map((cc) => cc.colId);
        notExistingColumnIds.forEach((colId) => {
            this.logWarn(`Column with id ${colId} does not exist, could NOT update configuration`);
        });
        const agGridApi = this._adaptable.agGridAdapter.getAgGridApi();
        agGridApi.applyColumnState({
            state: existingColumnStates,
        });
    }
    setAgGridColumnDefinitions(columnDefinitions) {
        const agGridApi = this._adaptable.agGridAdapter.getAgGridApi();
        agGridApi.setGridOption('columnDefs', columnDefinitions);
    }
    updateAgGridColumnDefinition(columnDefinitionToBeUpdated) {
        const currentColDefs = [...this._adaptable.agGridAdapter.getAgGridApi().getColumnDefs()];
        const columnId = columnDefinitionToBeUpdated.colId;
        const doesColumnExist = this.getColumnApi().doesColumnExist(columnId);
        if (!doesColumnExist) {
            this.logWarn(`Column with id ${columnId} does not exist, will add it instead!`);
            const newColDefs = [...currentColDefs, columnDefinitionToBeUpdated];
            this.setAgGridColumnDefinitions(newColDefs);
            return;
        }
        const updatedColDefs = this._adaptable.agGridAdapter.traverseColDefs(currentColDefs, (colDef) => {
            return colDef.colId === columnId ? { ...colDef, ...columnDefinitionToBeUpdated } : colDef;
        });
        this.setAgGridColumnDefinitions(updatedColDefs);
    }
    updateAgGridColumnDefinitions(columnDefinitionsToBeUpdated) {
        const currentColDefs = [...this._adaptable.agGridAdapter.getAgGridApi().getColumnDefs()];
        const updatedColDefs = this._adaptable.agGridAdapter.traverseColDefs(currentColDefs, (colDef) => {
            const newColDef = newColumnDefinitions.find((c) => c.colId === colDef.colId);
            return newColDef ? { ...colDef, ...newColDef } : colDef;
        });
        // find out new columns which are not in the current column definitions
        const currentColIds = [];
        this._adaptable.agGridAdapter.traverseColDefs(currentColDefs, (colDef) => {
            currentColIds.push(colDef.colId);
            return colDef;
        });
        const newColumnDefinitions = columnDefinitionsToBeUpdated.filter((c) => !currentColIds.includes(c.colId));
        if (newColumnDefinitions.length) {
            this.logWarn(`Columns with ids ${newColumnDefinitions
                .map((c) => c.colId)
                .join(', ')} do not exist, will add them instead!`);
        }
        this.setAgGridColumnDefinitions([...updatedColDefs, ...newColumnDefinitions]);
    }
    removeAgGridColumnDefinition(columnId) {
        const doesColumnExist = this.getColumnApi().doesColumnExist(columnId);
        if (!doesColumnExist) {
            this.logWarn(`Column with id ${columnId} does not exist!`);
            return;
        }
        const currentColDefs = this._adaptable.agGridAdapter.getAgGridApi().getColumnDefs();
        const updatedColDefs = this._adaptable.agGridAdapter
            .traverseColDefs(currentColDefs, (colDef) => {
            return colDef.colId === columnId ? null : colDef;
        })
            .filter(Boolean);
        this.setAgGridColumnDefinitions(updatedColDefs);
    }
    addAgGridColumnDefinition(newColumnDefinition) {
        const currentColDefs = this.getAgGridColumnDefs();
        // just in case check of there is not already an existing column with the same id and eliminate it
        const sanitizedColDefs = this._adaptable.agGridAdapter
            .traverseColDefs(currentColDefs, (colDef) => {
            return colDef.colId === newColumnDefinition.colId ? null : colDef;
        })
            .filter(Boolean);
        this.setAgGridColumnDefinitions([...sanitizedColDefs, newColumnDefinition]);
    }
}
