"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgGridColumnAdapter = exports.getEditorForColumnDataType = void 0;
const tslib_1 = require("tslib");
const kebabCase_1 = tslib_1.__importDefault(require("lodash/kebabCase"));
const merge_1 = tslib_1.__importDefault(require("lodash/merge"));
const StyleHelper_1 = require("../Utilities/Helpers/StyleHelper");
const StringExtensions_1 = tslib_1.__importDefault(require("../Utilities/Extensions/StringExtensions"));
const AdaptableColumn_1 = require("../AdaptableState/Common/AdaptableColumn");
const tinycolor2_1 = tslib_1.__importDefault(require("tinycolor2"));
const UIHelper_1 = tslib_1.__importDefault(require("../View/UIHelper"));
const PercentBarRenderer_1 = require("./cellRenderers/PercentBarRenderer");
const BadgeRenderer_1 = require("./cellRenderers/BadgeRenderer");
const Helper_1 = tslib_1.__importDefault(require("../Utilities/Helpers/Helper"));
const AdaptableNumberEditor_1 = require("./editors/AdaptableNumberEditor");
const AdaptableDateEditor_1 = require("./editors/AdaptableDateEditor");
const AgGridExportAdapter_1 = require("./AgGridExportAdapter");
const AdaptableHelper_1 = require("../Utilities/Helpers/AdaptableHelper");
const adaptableOverrideCheck_1 = require("../Utilities/adaptableOverrideCheck");
const AdaptableFilterHandler_1 = require("./AdaptableFilterHandler");
const AgGridFilterAdapter_1 = require("./AgGridFilterAdapter");
const AgGridFloatingFilterAdapter_1 = require("./AgGridFloatingFilterAdapter");
const AdaptableLogger_1 = require("./AdaptableLogger");
function getEditorForColumnDataType(columnDataType, variant) {
    if (columnDataType === 'number') {
        return variant === 'react' ? AdaptableNumberEditor_1.AdaptableReactNumberEditor : AdaptableNumberEditor_1.AdaptableNumberEditor;
    }
    if (columnDataType === 'date') {
        return variant === 'react' ? AdaptableDateEditor_1.AdaptableReactDateEditor : AdaptableDateEditor_1.AdaptableDateEditor;
    }
}
exports.getEditorForColumnDataType = getEditorForColumnDataType;
class AgGridColumnAdapter {
    constructor(adaptableInstance) {
        this.adaptableInstance = adaptableInstance;
        this.colDefPropertyCache = new Map();
    }
    getVariant() {
        return this.adaptableInstance.variant;
    }
    destroy() {
        this.adaptableInstance = null;
        this.colDefPropertyCache.clear();
        this.colDefPropertyCache = null;
    }
    get adaptableApi() {
        return this.adaptableInstance.api;
    }
    get adaptableOptions() {
        return this.adaptableInstance.adaptableOptions;
    }
    get agGridApi() {
        return this.adaptableApi.agGridApi;
    }
    setColDefProperty(col, propertyName, propertyGetter) {
        const colId = col.getColId();
        const colDef = col.getColDef();
        const colSetupInfo = {
            col,
            colDef,
            colId,
        };
        const userKey = `user.${colId}.${propertyName}`;
        const adaptableKey = `adaptable.${colId}.${propertyName}`;
        const value = colDef[propertyName];
        const isUserDefined = value !== this.colDefPropertyCache.get(adaptableKey);
        if (isUserDefined) {
            this.colDefPropertyCache.set(userKey, value);
        }
        const userValue = this.colDefPropertyCache.get(userKey);
        const adaptableValue = propertyGetter(userValue);
        if (adaptableValue != null) {
            this.colDefPropertyCache.set(adaptableKey, adaptableValue);
        }
        let theValue = adaptableValue ?? userValue;
        this.adaptableInstance.forPlugins((plugin) => {
            if (plugin.interceptSetupColumnProperty) {
                theValue = plugin.interceptSetupColumnProperty(colSetupInfo, propertyName, theValue, this.adaptableApi);
            }
        });
        if (propertyName === 'aggFunc') {
            if (colDef[propertyName] !== (theValue ?? null)) {
                this.agGridApi?.setColumnAggFunc(colId, theValue ?? null);
            }
        }
        if (theValue === undefined && colDef[propertyName] === undefined) {
            // already undefined, so don't set an own property to the same undefined value
            return;
        }
        colDef[propertyName] = theValue;
    }
    getUserColDefProperty(columnId, propertyName) {
        const userKey = `user.${columnId}.${propertyName}`;
        return this.colDefPropertyCache.get(userKey);
    }
    shouldSkipColumn(colId) {
        /**
         * This skips special columns that ag grid will likely implement in the future
         *
         * BUT DOES NOT SKIP GROUP COLUMNS or SELECTION COLUMNS!!!
         *
         * It's probably here for historical reasons - previously it used to skip the selection column
         * but now it's not skipping it anymore
         */
        return (colId.startsWith('ag-Grid-') &&
            !this.adaptableApi.columnApi.isAutoRowGroupColumn(colId) &&
            !this.adaptableApi.columnApi.isSelectionColumn(colId));
    }
    setupColumns() {
        const pivotMode = this.adaptableInstance.isInPivotMode();
        let cols = pivotMode
            ? // for pivot mode, we take only the initial columns
                this.agGridApi.getColumns()
            : // but for non-pivot mode, we ask for all columns
                // which also includes those that are generated for row grouping
                this.agGridApi.getAllGridColumns();
        if (pivotMode) {
            const pivotResultColumns = this.agGridApi.getPivotResultColumns() || [];
            const autoGroupColumns = this.agGridApi
                .getAllGridColumns()
                .filter((column) => this.adaptableApi.columnApi.isAutoRowGroupColumn(column.getColId()));
            cols = [...autoGroupColumns, ...cols, ...pivotResultColumns];
        }
        // this needs to be here, before the other setup below
        // so the setup methods below reference the correct columns in adaptable store
        cols.forEach((col) => {
            const colDef = col.getColDef();
            const colId = col.getColId();
            if (this.shouldSkipColumn(colId)) {
                return;
            }
            const abColumn = this.adaptableApi.columnApi.getColumnWithColumnId(colId);
            const colSetupInfo = {
                col,
                colDef,
                colId,
                abColumn,
            };
            this.setupColumnCellRenderer(colSetupInfo);
            this.setupColumnCellStyle(colSetupInfo);
            this.setupColumnCellClass(colSetupInfo);
            this.setupColumnHeaderStyle(colSetupInfo);
            this.setupColumnHeaderClass(colSetupInfo);
            this.setupColumnValueGetter(colSetupInfo);
            this.setupColumnTooltipValueGetter(colSetupInfo);
            this.setupColumnFilter(colSetupInfo);
            this.setupColumnFloatingFilter(colSetupInfo);
            this.setupColumnValueFormatter(colSetupInfo);
            this.setupColumnEditable(colSetupInfo);
            this.setupColumnValueSetter(colSetupInfo);
            this.setupColumnComparator(colSetupInfo);
            this.setupColumnGetFindText(colSetupInfo);
            this.setupColumnCellEditor(colSetupInfo);
            this.setupColumnHeader(colSetupInfo);
            this.setupColumnQuickFilterText(colSetupInfo);
            this.setupColumnAllowedAggFuncs(colSetupInfo);
            this.setupColumnType(colSetupInfo);
            this.setupColumnCellDataType(colSetupInfo);
        });
    }
    setupColumnValueGetter({ col }) {
        // need this here if we want plugins to intercept
        this.setColDefProperty(col, 'valueGetter', (userValue) => {
            return userValue;
        });
    }
    setupColumnCellClass({ col, colId, abColumn }) {
        this.setColDefProperty(col, 'cellClass', (userCellClass) => {
            const formatColumns = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnWithStyleClassNameForColumn(abColumn, { target: 'cell' });
            const quickSearchTextMatchStyle = this.getQuickSearchTextMatchStyle();
            const quickSearchCurrentTextMatchStyle = this.getQuickSearchCurrentTextMatchStyle();
            const cellClass = (params) => {
                const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, abColumn.columnId);
                if (!gridCell.column) {
                    return null;
                }
                const isExcelExport = this.adaptableApi.exportApi.internalApi.isExcelExportInProgress();
                const isVisualDataExport = this.adaptableApi.exportApi.internalApi.isVisualDataExportInProgress();
                if (isExcelExport || isVisualDataExport) {
                    const excelStyleClasses = [];
                    const userDefinedCellClass = typeof userCellClass === 'function' ? userCellClass(params) : userCellClass;
                    if (userDefinedCellClass) {
                        if (Array.isArray(userDefinedCellClass)) {
                            excelStyleClasses.push(...userDefinedCellClass.filter(Boolean));
                        }
                        else {
                            excelStyleClasses.push(userDefinedCellClass);
                        }
                    }
                    if (isVisualDataExport) {
                        const cellClassKey = AgGridExportAdapter_1.AgGridExportAdapter.getExcelClassNameForCell(colId, gridCell.primaryKeyValue, userDefinedCellClass);
                        const customCellClass = this.adaptableInstance.agGridExportAdapter.getExcelStyleIdForCellClassKey(cellClassKey);
                        if (customCellClass) {
                            excelStyleClasses.push(customCellClass);
                        }
                    }
                    return excelStyleClasses.length ? excelStyleClasses : null;
                }
                const isQuickSearchActive = this.isQuickSearchActive(gridCell);
                const editableClassName = this.getEditableCellClass(gridCell, params);
                const readonlyClassName = this.getReadonlyCellClass(gridCell, params);
                const editedClassName = this.getEditedCellClass(gridCell, params);
                const highlightAlertClassName = this.getAlertCellClass(gridCell, params);
                const flashingClassName = this.getFlashingCellClass(gridCell, params);
                const styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(colId);
                const hasStyledColumn = !!styledColumn && !styledColumn.IsSuspended;
                const noteClassName = this.getNoteCellClassName(gridCell, params);
                const commentsClassName = this.getCommentCellClassName(gridCell, params);
                const returnValue = [
                    typeof userCellClass === 'function' ? userCellClass(params) : userCellClass,
                    !hasStyledColumn && formatColumns.length
                        ? this.getFormatColumnCellClass(formatColumns, abColumn, params)
                        : null,
                    //  isQuickSearchActive && hasQuickSearchStyleClassName ? quickSearchStyleClassName : null,
                    isQuickSearchActive && (quickSearchTextMatchStyle || quickSearchCurrentTextMatchStyle)
                        ? 'ab-QuickSearchFind'
                        : null,
                    editableClassName,
                    readonlyClassName,
                    editedClassName,
                    highlightAlertClassName,
                    flashingClassName,
                    noteClassName,
                    commentsClassName,
                ]
                    // we flatten the array because some rules ('userCellClass' etc)  might return a string[]
                    .flat()
                    .filter((x) => !!x);
                const result = returnValue.length ? returnValue : undefined;
                return result;
            };
            return cellClass;
        });
    }
    setupColumnHeaderClass({ col, colId, abColumn }) {
        this.setColDefProperty(col, 'headerClass', (userHeaderClass) => {
            const headerClass = (params) => {
                let baseHeaderClass = [];
                // inherit styles from user provided colDef property
                const userDefinedHeaderClass = typeof userHeaderClass === 'function' ? userHeaderClass(params) : userHeaderClass;
                if (userDefinedHeaderClass) {
                    baseHeaderClass =
                        typeof userDefinedHeaderClass === 'string'
                            ? [userDefinedHeaderClass]
                            : Array.isArray(userDefinedHeaderClass)
                                ? userDefinedHeaderClass
                                : [userDefinedHeaderClass];
                }
                if (params.floatingFilter) {
                    // we NEVER style floating filters
                    return baseHeaderClass;
                }
                if (params.columnGroup) {
                    // we TEMPORARILY do NOT style column groups
                    // see https://github.com/AdaptableTools/adaptable/issues/2947#issuecomment-3062304655
                    return baseHeaderClass;
                }
                const columnId = params.column.getColId();
                const adaptableColumn = this.adaptableApi.columnApi.getColumnWithColumnId(columnId);
                if (!adaptableColumn) {
                    return baseHeaderClass;
                }
                const target = 'columnHeader';
                // handle special case of headers with text alignment
                // in this case, we add a specific class to the header
                // see #header_text_align
                const formatColumnWithTextAlignment = this.getRelevantFormatColumnHeaderStyles(abColumn)
                    // we take the first one only, even if multiple are defined
                    .find((fc) => fc.CellAlignment != undefined);
                if (formatColumnWithTextAlignment) {
                    baseHeaderClass = [
                        ...baseHeaderClass,
                        `ab-header__align-${formatColumnWithTextAlignment.CellAlignment.toLowerCase()}`,
                    ];
                }
                const formatColumns = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnWithStyleClassNameForColumn(abColumn, {
                    target,
                });
                if (!formatColumns.length) {
                    return baseHeaderClass;
                }
                const formatColumnClasses = formatColumns
                    .map((formatColumn) => {
                    if (formatColumn.Style?.ClassName &&
                        this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInHeader(formatColumn, abColumn)) {
                        return formatColumn.Style?.ClassName;
                    }
                })
                    .filter((x) => !!x);
                return [...baseHeaderClass, ...formatColumnClasses];
            };
            return headerClass;
        });
    }
    setupColumnCellStyle({ col }) {
        this.setColDefProperty(col, 'cellStyle', (userCellStyle) => {
            const quickSearchStyle = this.getQuickSearchCellStyle();
            const quickSearchTextMatchStyle = this.getQuickSearchTextMatchStyle();
            const quickSearchCurrentTextMatchStyle = this.getQuickSearchCurrentTextMatchStyle();
            const textMatchStyle = quickSearchTextMatchStyle
                ? Object.entries(quickSearchTextMatchStyle).reduce((acc, [key, value]) => {
                    // needed as AG-Grid vanilla turns all CSS props
                    // to kebab, while AG Grid React does not
                    // @ts-ignore
                    acc[`--ab-dynamic-${(0, kebabCase_1.default)(key)}`] = value;
                    return acc;
                }, {})
                : undefined;
            const currentTextMatchStyle = quickSearchCurrentTextMatchStyle
                ? Object.entries(quickSearchCurrentTextMatchStyle).reduce((acc, [key, value]) => {
                    // @ts-ignore
                    acc[`--ab-dynamic-${(0, kebabCase_1.default)(key)}`] = value;
                    return acc;
                }, {})
                : undefined;
            const hasQuickSearchStyle = quickSearchStyle != undefined || quickSearchCurrentTextMatchStyle != undefined;
            const cellStyle = (params) => {
                const columnId = params.column.getColId();
                const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, columnId);
                if (!gridCell || !gridCell.column) {
                    return {};
                }
                const isQuickSearchActive = hasQuickSearchStyle && this.isQuickSearchActive(gridCell);
                const isQuickSearchAvailable = this.adaptableApi.internalApi
                    .getModuleService()
                    .isAdapTableModulePresent('QuickSearch');
                const isCurrentMatch = isQuickSearchAvailable &&
                    this.adaptableApi.agGridApi.findGetActiveMatch()?.node === params.node;
                const textStyleToApply = isCurrentMatch
                    ? { ...textMatchStyle, ...currentTextMatchStyle }
                    : textMatchStyle;
                let baseStyles = {};
                // this is required because otherwise, when AG Grid filters, it refreshed the pivotResultColDef and the base styles get lost
                // if pivot result col: inherit styles from base column
                if (this.adaptableApi.columnApi.isPivotResultColumn(columnId)) {
                    const baseColumn = params.column.getColDef()?.pivotValueColumn;
                    if (baseColumn) {
                        const baseColDefCellStyle = baseColumn?.getColDef()?.cellStyle;
                        const baseColParams = {
                            ...params,
                            column: baseColumn,
                            // @ts-ignore
                            // #derived_pivot_cell_style
                            __pivotResultColumn: params.column,
                        };
                        baseStyles =
                            typeof baseColDefCellStyle === 'function'
                                ? baseColDefCellStyle(baseColParams)
                                : baseColDefCellStyle;
                    }
                }
                else {
                    // inherit styles from user provided colDef property
                    baseStyles = typeof userCellStyle === 'function' ? userCellStyle(params) : userCellStyle;
                }
                const result = {
                    ...baseStyles,
                    ...this.getReadOnlyCellStyle(gridCell, params),
                    ...this.getEditableCellStyle(gridCell, params),
                    ...this.getEditedCellStyle(gridCell, params),
                    ...this.getFormatColumnAndStyledColumnCellStyle(gridCell.column, params),
                    ...(isQuickSearchActive ? quickSearchStyle : {}),
                    ...(isQuickSearchActive && textStyleToApply ? textStyleToApply : {}),
                    ...this.getAlertCellStyle(gridCell, params),
                    ...this.getFlashingCellStyle(gridCell, params),
                    ...this.getCellHighlightStyle(gridCell, params),
                };
                return (0, StyleHelper_1.normalizeStyleForAgGrid)(result);
            };
            return cellStyle;
        });
    }
    setupColumnHeaderStyle({ col }) {
        this.setColDefProperty(col, 'headerStyle', (userHeaderStyle) => {
            const headerStyleFunc = (params) => {
                let baseStyles = {};
                // inherit styles from user provided colDef property
                baseStyles =
                    typeof userHeaderStyle === 'function' ? userHeaderStyle(params) : userHeaderStyle;
                if (params.floatingFilter) {
                    // we NEVER style floating filters
                    return baseStyles;
                }
                const columnId = params.column.getColId();
                const adaptableColumn = this.adaptableApi.columnApi.getColumnWithColumnId(columnId);
                if (!adaptableColumn) {
                    return baseStyles;
                }
                const result = {
                    ...baseStyles,
                    ...this.getFormatColumnHeaderStyle(adaptableColumn, params),
                };
                if (result['borderColor']) {
                    // by default, header cells don't have a border
                    // if the user defines a border-color, we assume he wants to show a border
                    result['borderWidth'] = `1px`;
                    result['borderStyle'] = 'solid';
                }
                return (0, StyleHelper_1.normalizeStyleForAgGrid)(result);
            };
            return headerStyleFunc;
        });
    }
    setupColumnCellEditor({ colId, col, colDef, abColumn }) {
        const shouldShowSelectCellEditor = this.adaptableApi.userInterfaceApi.internalApi.shouldShowSelectCellEditor(abColumn);
        const hasRichSelectCellEditor = this.adaptableApi.internalApi
            .getAgGridModulesAdapter()
            .isAgGridModuleRegistered('RichSelectModule');
        this.setColDefProperty(col, 'cellEditor', () => {
            if (shouldShowSelectCellEditor) {
                if (hasRichSelectCellEditor) {
                    return 'agRichSelectCellEditor';
                }
                else {
                    this.adaptableApi.logWarn(`Cannot show Select Editor as missing required AG Grid module: RichSelect`);
                    return colDef.cellEditor;
                }
            }
            else {
                if (colDef.cellEditor) {
                    return colDef.cellEditor;
                }
                const cellDataTypeEditor = getEditorForColumnDataType(abColumn.dataType, this.getVariant());
                return cellDataTypeEditor;
            }
        });
        this.setColDefProperty(col, 'cellEditorParams', (params) => {
            if (shouldShowSelectCellEditor) {
                return (params) => {
                    const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params?.node, colId);
                    const options = this.adaptableApi.gridApi.internalApi.getDistinctEditDisplayValuesForColumn({
                        columnId: colId,
                        gridCell,
                        currentSearchValue: '',
                    });
                    const valueToLabelMap = new Map();
                    const values = options.then((options) => options.map((option) => {
                        valueToLabelMap.set(option.value, option.label);
                        return option.value;
                    }));
                    return {
                        values,
                        formatValue: (value) => valueToLabelMap.get(value) ?? value,
                    };
                };
            }
        });
    }
    setupColumnCellRenderer({ col, colId, abColumn }) {
        this.setColDefProperty(col, 'cellRenderer', () => {
            const styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(abColumn.columnId);
            if (styledColumn && !styledColumn.IsSuspended) {
                if (styledColumn.PercentBarStyle) {
                    return (0, PercentBarRenderer_1.getPercentBarRendererForColumn)(styledColumn, abColumn, this.adaptableApi);
                }
                if (styledColumn.BadgeStyle) {
                    return (0, BadgeRenderer_1.getBadgeRendererForColumn)(styledColumn.BadgeStyle, abColumn, this.adaptableApi);
                }
                if (styledColumn.SparklineStyle) {
                    return 'agSparklineCellRenderer';
                }
            }
        });
        this.setColDefProperty(col, 'cellRendererParams', (userDefined) => {
            const styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(abColumn.columnId);
            if (styledColumn && !styledColumn.IsSuspended) {
                if (styledColumn.SparklineStyle) {
                    const sanitizedSparklineOptions = AdaptableHelper_1.AdaptableHelper.removeAdaptableObjectPrimitives(styledColumn.SparklineStyle.options);
                    const sparklineOptions = (0, merge_1.default)({}, userDefined?.sparklineOptions, sanitizedSparklineOptions);
                    return {
                        ...userDefined,
                        sparklineOptions,
                    };
                }
            }
        });
    }
    setupColumnTooltipValueGetter({ col, colId, abColumn }) {
        let hasTooptip = false;
        this.setColDefProperty(col, 'tooltipValueGetter', () => {
            const styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(colId);
            if (styledColumn &&
                !styledColumn.IsSuspended &&
                styledColumn.PercentBarStyle &&
                styledColumn.PercentBarStyle.ToolTipText) {
                hasTooptip = true;
                if (styledColumn?.PercentBarStyle) {
                    return (params) => {
                        const min = this.adaptableApi.styledColumnApi.internalApi.getNumericStyleMinValue(styledColumn, abColumn, params.node, params.value);
                        const max = this.adaptableApi.styledColumnApi.internalApi.getNumericStyleMaxValue(styledColumn, abColumn, params.node, params.value);
                        const textOptions = styledColumn.PercentBarStyle.ToolTipText;
                        let returnValue = '';
                        if (textOptions.includes('CellValue')) {
                            returnValue = params.value;
                        }
                        if (textOptions.includes('PercentageValue')) {
                            const clampedValue = Helper_1.default.clamp(params.value, min, max);
                            const percentageValue = ((clampedValue - min) / (max - min)) * 100;
                            returnValue += ' ' + `(${percentageValue.toFixed(0)}%)`;
                        }
                        return returnValue ? returnValue : params.value;
                    };
                }
            }
        });
    }
    setupColumnQuickFilterText({ col, abColumn }) {
        this.setColDefProperty(col, 'getQuickFilterText', (userGetQuickFilterText) => {
            if (userGetQuickFilterText) {
                return userGetQuickFilterText;
            }
            return (params) => {
                const visibleColumnsMap = this.adaptableApi.layoutApi.getCurrentVisibleColumnIdsMapForTableLayout();
                const isVisible = visibleColumnsMap[abColumn.columnId];
                if (!isVisible) {
                    return '';
                }
                return this.adaptableApi.gridApi.getDisplayValueFromRowNode(params.node, abColumn.columnId);
            };
        });
    }
    setupColumnAllowedAggFuncs({ col, abColumn }) {
        this.setColDefProperty(col, 'allowedAggFuncs', () => {
            return abColumn.availableAggregationFunctions;
        });
    }
    setupColumnType(columnSetupInfo) {
        const { col, colId } = columnSetupInfo;
        // AG Grid introduced since v30.x an inferred cellDataType
        // the problem is that it breaks the default value formatter and/or editor (especially for Date columns)
        this.setColDefProperty(col, 'type', (original_columnType) => {
            const originalTypes = original_columnType == undefined
                ? []
                : Array.isArray(original_columnType)
                    ? original_columnType
                    : [original_columnType];
            const columnTypes = new Set(originalTypes);
            if (this.adaptableApi.columnApi.isCalculatedColumn(colId)) {
                columnTypes.add(AdaptableColumn_1.CALCULATED_COLUMN_TYPE);
            }
            if (this.adaptableApi.columnApi.isFreeTextColumn(colId)) {
                columnTypes.add(AdaptableColumn_1.FREE_TEXT_COLUMN_TYPE);
            }
            if (this.adaptableApi.columnApi.isActionColumn(colId)) {
                columnTypes.add(AdaptableColumn_1.ACTION_COLUMN_TYPE);
            }
            if (this.adaptableApi.columnApi.isFdc3Column(colId)) {
                columnTypes.add(AdaptableColumn_1.FDC3_COLUMN_TYPE);
            }
            return Array.from(columnTypes);
        });
    }
    setupColumnCellDataType(columnSetupInfo) {
        const { col, colId } = columnSetupInfo;
        this.setColDefProperty(col, 'cellDataType', (original_cellDataType) => {
            // #map_dateString_to_date
            if (original_cellDataType === 'dateString') {
                (0, AdaptableLogger_1.errorOnce)(`AG Grid: Column '${colId}' specifies cellDataType='dateString' which is no longer supported. It has been automatically replaced with cellDataType='date'. Please update your column definition.`);
                return 'date';
            }
            return original_cellDataType ?? true;
        });
    }
    setupColumnHeader({ col }) {
        this.setColDefProperty(col, 'headerValueGetter', (original_headerValueGetter) => {
            // see #customize_header
            if (!(0, adaptableOverrideCheck_1.isProvidedByAdaptable)(original_headerValueGetter)) {
                this.adaptableApi.logWarn(`colDef.headerValueGetter is defined for column '${col.getColId()}', and overrides the Adaptable custom header mechanism! We recommend using a ColumnOptions.columnHeader instead!`);
            }
            return original_headerValueGetter;
        });
    }
    setupColumnFilter(columnSetup) {
        const { col, colDef, abColumn, colId } = columnSetup;
        const useAdaptableFilter = this.adaptableOptions.filterOptions.useAdaptableFiltering;
        if (!useAdaptableFilter) {
            return;
        }
        // setup Auto Group Column Filter
        if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
            if (this.adaptableApi.gridApi.isTreeDataGrid()) {
                this.setColDefProperty(col, 'filter', (original_filter) => {
                    const autoGroupColumnDef = this.agGridApi.getGridOption('autoGroupColumnDef');
                    if (autoGroupColumnDef.filter != undefined) {
                        // we plan to provide a TreeListColumnFilter
                        // until then, it's the user's responsibility to explicitly set the filter in the provided `autoGroupColumnDef`
                        return original_filter;
                    }
                    else {
                        // if no filter is explicitly set, we do NOT provide a filter
                        return false;
                    }
                });
            }
            else {
                this.setColDefProperty(col, 'filter', () => {
                    return 'agGroupColumnFilter';
                });
            }
            return;
        }
        // setup "normal" column filter
        this.setColDefProperty(col, 'filter', (original_filter) => {
            if (!colDef.filter) {
                return;
            }
            if (!useAdaptableFilter) {
                return original_filter;
            }
            if (useAdaptableFilter &&
                typeof original_filter !== 'boolean' &&
                typeof original_filter?.handler !== 'function' &&
                !this.adaptableInstance.isInPivotMode()) {
                this.adaptableApi.consoleError(`Column '${colId}' has a custom filter defined in colDef.filter, but Adaptable Filtering accepts only the TRUE/FALSE values!`);
                return false;
            }
            return {
                component: (0, AgGridFilterAdapter_1.AgGridFilterAdapterFactory)(this.adaptableInstance),
                // doesFilterPass,
                handler: (params) => new AdaptableFilterHandler_1.AdaptableFilterHandler(this.adaptableApi, columnSetup),
            };
        });
    }
    setupColumnFloatingFilter({ col, colDef }) {
        const userProvidedFilterProp = this.getUserColDefProperty(col.getColId(), 'filter');
        const hasInvalidFilterProp = typeof userProvidedFilterProp !== 'boolean' &&
            typeof userProvidedFilterProp?.handler !== 'function' &&
            !this.adaptableInstance.isInPivotMode();
        if (hasInvalidFilterProp) {
            // warning is logged in the 'setupColumnFilter' method
            return false;
        }
        const isFloatingFilterDisabled = !colDef.filter ||
            !colDef.floatingFilter ||
            !this.adaptableOptions.filterOptions.useAdaptableFiltering ||
            !this.adaptableApi.filterApi.columnFilterApi.isQuickFilterVisible();
        if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
            this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
                // the floating filter for the group column is "inherited" from the base column
                // via the colDef.filter =  'agGroupColumnFilter'
                // see #group_inherit_column_filter
                // https://www.ag-grid.com/javascript-data-grid/grouping-single-group-column/#inherit-row-grouped-columns-filters
                // https://www.ag-grid.com/javascript-data-grid/grouping-multiple-group-columns/#filtering
                return original_floatingFilter;
            });
            this.setColDefProperty(col, 'suppressFloatingFilterButton', () => {
                // hide button for multi column groups
                return this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(col.getColId());
            });
            return;
        }
        this.setColDefProperty(col, 'floatingFilterComponent', () => {
            if (isFloatingFilterDisabled) {
                return;
            }
            return (0, AgGridFloatingFilterAdapter_1.AgGridFloatingFilterAdapterFactory)(this.adaptableInstance);
        });
        this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
            if (isFloatingFilterDisabled) {
                return;
            }
            return (0, AgGridFloatingFilterAdapter_1.AgGridFloatingFilterAdapterFactory)(this.adaptableInstance);
        });
        this.setColDefProperty(col, 'suppressFloatingFilterButton', () => {
            return !isFloatingFilterDisabled;
        });
    }
    setupColumnValueFormatter({ col, abColumn }) {
        this.setColDefProperty(col, 'valueFormatter', (userPropertyValue) => {
            const activeFormatColumnsWithDisplayFormat = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnsWithDisplayFormatForColumn(abColumn, { target: 'cell' });
            if (!activeFormatColumnsWithDisplayFormat.length) {
                return;
            }
            return (params) => {
                const { node, value } = params;
                const mostRelevantFormatColumn = this.adaptableApi.formatColumnApi.internalApi.getMostRelevantFormatColumnForColumn(activeFormatColumnsWithDisplayFormat, abColumn, { node, value });
                if (!mostRelevantFormatColumn) {
                    // ALL FormatColumns are conditional and NONE of them are relevant for this row
                    return value;
                }
                const formatterOptions = mostRelevantFormatColumn.DisplayFormat.Options;
                if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'NumberFormatter') {
                    // change the Number format - if the scope allows it
                    if (this.adaptableApi.columnScopeApi.isColumnInNumericScope(abColumn, mostRelevantFormatColumn.Scope)) {
                        let cellValue = params.value;
                        if (typeof params.value?.toNumber === 'function' &&
                            typeof params.value?.toString === 'function') {
                            // aggregation values are wrapped in an AG Grid specific object
                            cellValue = params.value.toNumber();
                        }
                        return this.adaptableApi.formatColumnApi.internalApi.getNumberFormattedValue(cellValue, params.node, abColumn, formatterOptions);
                    }
                }
                if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'DateFormatter') {
                    // change the Date format - if the scope allows it
                    if (this.adaptableApi.columnScopeApi.isColumnInDateScope(abColumn, mostRelevantFormatColumn.Scope)) {
                        let cellValue = params.value;
                        if (typeof params.value?.toNumber === 'function' &&
                            typeof params.value?.toString === 'function') {
                            // aggregation values are wrapped in an AG Grid specific object
                            cellValue = params.value.toString();
                        }
                        return this.adaptableApi.formatColumnApi.internalApi.getDateFormattedValue(cellValue, params.node, abColumn, formatterOptions);
                    }
                }
                if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'StringFormatter') {
                    // change the String format - if the scope allows it
                    if (this.adaptableApi.columnScopeApi.isColumnInTextScope(abColumn, mostRelevantFormatColumn.Scope)) {
                        let cellValue = params.value;
                        if (typeof params.value?.toNumber === 'function' &&
                            typeof params.value?.toString === 'function') {
                            // aggregation values are wrapped in an AG Grid specific object
                            cellValue = params.value.toString();
                        }
                        return this.adaptableApi.formatColumnApi.internalApi.getStringFormattedValue(cellValue, params.node, abColumn, formatterOptions);
                    }
                }
                // should NEVER arrive at this line, but just to be sure
                return value;
            };
        });
    }
    setupColumnEditable({ col }) {
        this.setColDefProperty(col, 'editable', (original_editable) => {
            // cell is NOT editable by default
            const editableCallback = (params) => {
                const getOriginalColDefEditable = () => {
                    if (typeof original_editable === 'function') {
                        return original_editable(params);
                    }
                    else {
                        return original_editable;
                    }
                };
                // 1. evaluate EditOptions.isCellEditable if provided
                if (this.adaptableApi.gridApi.internalApi.hasCellEditableAccordingToEditOptions()) {
                    const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, params.column.getColId());
                    const editOptionsEditability = this.adaptableApi.gridApi.internalApi.isCellEditableAccordingToEditOptions(gridCell, getOriginalColDefEditable());
                    if (editOptionsEditability) {
                        return editOptionsEditability;
                    }
                }
                // 2. otherwise, fallback to colDef.editable
                return getOriginalColDefEditable();
            };
            return editableCallback;
        });
    }
    setupColumnValueSetter({ col, colId, abColumn }) {
        this.setColDefProperty(col, 'valueSetter', (userValueSetter) => {
            const preventEditAlertsForColumn = this.adaptableApi.alertApi.internalApi
                .getAlertDefinitionsWithPreventEdit()
                .filter((alertDefinition) => {
                return this.adaptableApi.columnScopeApi.isColumnInScope(abColumn, alertDefinition.Scope);
            });
            const noValidations = !preventEditAlertsForColumn.length && !this.adaptableOptions.editOptions?.validateOnServer;
            if (noValidations) {
                return;
            }
            const valueSetter = (params) => {
                const field = params.column.getColDef().field;
                if (noValidations) {
                    //TODO also consider the case when userValueSetter is a string
                    if (typeof userValueSetter === 'function') {
                        return userValueSetter(params);
                    }
                    // we allowed it go reach this point
                    // just to run isCellEditable
                    // and since this has already run and we have no other validations
                    // just assign the new value and exit
                    if (field) {
                        params.data[field] = params.newValue;
                    }
                    return true;
                }
                const cellDataChangedInfo = this.adaptableApi.internalApi.buildCellDataChangedInfo({
                    oldValue: params.oldValue,
                    newValue: params.newValue,
                    column: this.adaptableApi.columnApi.getColumnWithColumnId(params.column.getColId()),
                    primaryKeyValue: this.adaptableApi.gridApi.getPrimaryKeyValueForRowNode(params.node),
                    rowNode: params.node,
                    trigger: 'edit',
                });
                if (cellDataChangedInfo.oldValue === cellDataChangedInfo.newValue) {
                    return true;
                }
                /**
                 * Validate on the future row, with the new value.
                 * structuredClone fails, it contains functions.
                 */
                const newRow = { ...params.node, data: { ...params.node.data } };
                newRow.data[field] = params.newValue;
                const cellDataChangeInfoForSyncValidation = {
                    ...cellDataChangedInfo,
                    rowNode: newRow,
                };
                if (!this.adaptableApi.internalApi
                    .getValidationService()
                    .performValidation(cellDataChangeInfoForSyncValidation)) {
                    return false;
                }
                const onServerValidationCompleted = () => { };
                if (this.adaptableOptions.editOptions?.validateOnServer) {
                    this.adaptableApi.internalApi
                        .getValidationService()
                        .performServerValidation(cellDataChangedInfo, {
                        onServerValidationCompleted,
                    })();
                }
                //TODO also consider the case when userValueSetter is a string
                if (typeof userValueSetter === 'function') {
                    return userValueSetter(params);
                }
                if (field) {
                    params.data[field] = params.newValue;
                }
                else {
                    throw `Cannot edit a column without a field - column id was ${colId}`;
                }
                return true;
            };
            return valueSetter;
        });
    }
    setupColumnComparator({ col, colId, abColumn }) {
        const customSort = this.adaptableApi.customSortApi.getCustomSortForColumn(colId);
        const customSortComparer = this.adaptableApi.customSortApi.internalApi.getCustomSortComparer(abColumn.columnId);
        const memoizedDateValues = new Map();
        const getDateValue = (rawDateValue) => {
            if (memoizedDateValues.has(rawDateValue)) {
                return memoizedDateValues.get(rawDateValue);
            }
            const dateValue = this.adaptableApi.internalApi.parseDateValue(rawDateValue);
            memoizedDateValues.set(rawDateValue, dateValue);
            return dateValue;
        };
        const comparatorGetter = (propName) => {
            return (userPropertyValue) => {
                // CustomSort Comparer function takes precedence over CustomSort SortedValues
                if (customSortComparer) {
                    return customSortComparer.comparer;
                }
                if (customSort && !customSort.IsSuspended) {
                    return this.adaptableApi.customSortApi.internalApi.getDefaultCustomSortComparer(customSort.ColumnId, customSort.SortedValues);
                }
                if (userPropertyValue) {
                    return userPropertyValue;
                }
                // for DATE columns we have to use the normalised values (Date objects) to compare
                if (abColumn.dataType === 'date') {
                    return (valueA, valueB) => {
                        const dateA = getDateValue(valueA);
                        const dateB = getDateValue(valueB);
                        if (dateA && dateB) {
                            return dateA.getTime() - dateB.getTime();
                        }
                        else if (dateA) {
                            return 1; // consider non-null dates as greater than null/undefined
                        }
                        else if (dateB) {
                            return -1; // consider non-null dates as greater than null/undefined
                        }
                        else {
                            return 0; // both are null/undefined, considered equal
                        }
                    };
                }
            };
        };
        this.setColDefProperty(col, 'comparator', comparatorGetter('comparator'));
        this.setColDefProperty(col, 'pivotComparator', comparatorGetter('pivotComparator'));
    }
    setupColumnGetFindText({ col, abColumn }) {
        this.setColDefProperty(col, 'getFindText', (userGetFindText) => {
            return (params) => {
                const gridCell = this.adaptableApi.gridApi.getGridCellFromRowNode(params.node, abColumn.columnId);
                if (!this.isCellSearchable(gridCell)) {
                    return null;
                }
                const getCellSearchText = this.adaptableOptions.quickSearchOptions.getCellSearchText;
                if (getCellSearchText) {
                    return this.getCellSearchText(gridCell);
                }
                return userGetFindText?.(params) ?? gridCell.displayValue;
            };
        });
    }
    getCellSearchText(gridCell) {
        const getCellSearchText = this.adaptableOptions.quickSearchOptions.getCellSearchText;
        if (getCellSearchText) {
            const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
            const quickSearchContext = {
                ...this.adaptableApi.internalApi.buildBaseContext(),
                gridCell,
                quickSearchValue,
            };
            return getCellSearchText(quickSearchContext);
        }
        return gridCell.displayValue;
    }
    isCellSearchable(gridCell) {
        const isCellSearchableFn = this.adaptableOptions.quickSearchOptions.isCellSearchable;
        if (!gridCell.column) {
            return false;
        }
        if (isCellSearchableFn) {
            const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
            const quickSearchContext = {
                ...this.adaptableApi.internalApi.buildBaseContext(),
                gridCell,
                quickSearchValue,
            };
            if (!isCellSearchableFn(quickSearchContext)) {
                return false;
            }
        }
        return true;
    }
    isQuickSearchActive(gridCell) {
        const isQuickSearchAvailable = this.adaptableApi.internalApi
            .getModuleService()
            .isAdapTableModulePresent('QuickSearch');
        if (!isQuickSearchAvailable) {
            return false;
        }
        const quickSearchValue = this.adaptableApi.quickSearchApi.getQuickSearchValue();
        if (!quickSearchValue) {
            return false;
        }
        if (!this.isCellSearchable(gridCell)) {
            return false;
        }
        let column = this.agGridApi.getColumn(gridCell.column.columnId);
        if (!column && this.adaptableApi.layoutApi.isCurrentLayoutPivot()) {
            column = this.agGridApi
                .getAllGridColumns()
                .find((col) => col.getColId() === gridCell.column.columnId);
        }
        if (!column) {
            return false;
        }
        const isServerSideRowModel = this.adaptableApi.gridApi.getAgGridRowModelType() === 'serverSide';
        if (isServerSideRowModel) {
            const isCaseSensitive = this.adaptableOptions.quickSearchOptions.isQuickSearchCaseSensitive;
            const cellDisplayValue = String(this.getCellSearchText(gridCell));
            const displayValue = isCaseSensitive
                ? cellDisplayValue
                : cellDisplayValue.toLocaleLowerCase();
            const searchText = isCaseSensitive ? quickSearchValue : quickSearchValue.toLocaleLowerCase();
            return displayValue.indexOf(searchText) !== -1;
        }
        return (this.agGridApi.findGetNumMatches({
            column,
            node: gridCell.rowNode,
        }) > 0);
    }
    getEditableCellClass(gridCell, params) {
        const editableCellStyle = this.adaptableApi.userInterfaceApi.getEditableCellStyle();
        if (!editableCellStyle?.ClassName) {
            return null;
        }
        const isCellEditable = this.adaptableApi.gridApi.isCellEditable(gridCell);
        return isCellEditable ? editableCellStyle.ClassName : null;
    }
    getReadonlyCellClass(gridCell, params) {
        const readonlyCellStyle = this.adaptableApi.userInterfaceApi.getReadOnlyCellStyle();
        if (!readonlyCellStyle?.ClassName) {
            return null;
        }
        const isCellReadonly = !this.adaptableApi.gridApi.isCellEditable(gridCell);
        return isCellReadonly ? readonlyCellStyle.ClassName : null;
    }
    getEditedCellClass(gridCell, params) {
        const editedCellStyle = this.adaptableApi.userInterfaceApi.getEditedCellStyle();
        if (!editedCellStyle?.ClassName) {
            return null;
        }
        const isCellEdited = this.adaptableApi.gridApi.isCellEdited(gridCell);
        return isCellEdited ? editedCellStyle.ClassName : null;
    }
    getAlertCellClass(gridCell, params) {
        const alert = this.adaptableApi.alertApi.internalApi.getAdaptableAlertWithHighlightCell(gridCell.column.columnId, params.node);
        const highlightCell = alert?.alertDefinition?.AlertProperties?.HighlightCell;
        return typeof highlightCell === 'object' && highlightCell?.ClassName
            ? highlightCell?.ClassName
            : null;
    }
    getFlashingCellClass(gridcell, params) {
        const primaryKey = params.node.aggData ? params.node.id : gridcell.primaryKeyValue;
        const flashingCell = this.adaptableApi.flashingCellApi.internalApi.getAdaptableFlashingCellFor(primaryKey, gridcell.column.columnId);
        if (!flashingCell) {
            return;
        }
        return flashingCell.direction === 'up'
            ? flashingCell.flashingCellDefinition.UpChangeStyle?.ClassName
            : flashingCell.direction === 'down'
                ? flashingCell.flashingCellDefinition.DownChangeStyle?.ClassName
                : flashingCell.direction === 'neutral'
                    ? flashingCell.flashingCellDefinition.NeutralChangeStyle?.ClassName
                    : undefined;
    }
    getNoteCellClassName(gridCell, params) {
        if (!this.adaptableApi.internalApi.getModuleService().isAdapTableModulePresent('Note')) {
            return;
        }
        if (!this.adaptableApi.noteApi.internalApi.areNotesSupported()) {
            return;
        }
        const cellPosition = {
            PrimaryKeyValue: gridCell.primaryKeyValue,
            ColumnId: gridCell.column.columnId,
        };
        const cellNote = this.adaptableApi.noteApi.getNoteForCell(cellPosition);
        if (!cellNote) {
            return undefined;
        }
        return 'ab-Cell-Note';
    }
    getCommentCellClassName(gridCell, params) {
        if (!this.adaptableApi.internalApi.getModuleService().isAdapTableModulePresent('Comment')) {
            return;
        }
        if (!this.adaptableApi.commentApi.internalApi.areCommentsSupportedInLayout()) {
            return;
        }
        const position = {
            PrimaryKeyValue: gridCell.primaryKeyValue,
            ColumnId: gridCell.column.columnId,
        };
        const cellComments = this.adaptableApi.commentApi.getCommentThreadForCell(position);
        if (!cellComments) {
            return undefined;
        }
        return 'ab-Cell-Comment';
    }
    getFormatColumnCellClass(formatColumns, abColumn, params) {
        const classNames = formatColumns
            .map((formatColumn) => {
            if (formatColumn.Style?.ClassName &&
                this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value)) {
                return formatColumn.Style?.ClassName;
            }
        })
            .filter((x) => !!x);
        return classNames;
    }
    getQuickSearchCellStyle() {
        const quickSearchStyle = this.adaptableApi.quickSearchApi.getQuickSearchCellMatchStyle();
        if (!quickSearchStyle || StringExtensions_1.default.IsNotNullOrEmpty(quickSearchStyle.ClassName)) {
            return undefined;
        }
        return (0, StyleHelper_1.convertAdaptableStyleToCSS)(quickSearchStyle);
    }
    getQuickSearchTextMatchStyle() {
        const quickSearchTextMatchStyle = this.adaptableApi.quickSearchApi.getQuickSearchTextMatchStyle();
        if (!quickSearchTextMatchStyle) {
            return undefined;
        }
        return (0, StyleHelper_1.convertAdaptableStyleToCSS)(quickSearchTextMatchStyle);
    }
    getQuickSearchCurrentTextMatchStyle() {
        const quickSearchCurrentTextMatchStyle = this.adaptableApi.quickSearchApi.getQuickSearchCurrentTextMatchStyle();
        if (!quickSearchCurrentTextMatchStyle) {
            return undefined;
        }
        return (0, StyleHelper_1.convertAdaptableStyleToCSS)(quickSearchCurrentTextMatchStyle);
    }
    getReadOnlyCellStyle(gridCell, params) {
        const editableCellStyle = this.adaptableApi.userInterfaceApi.getReadOnlyCellStyle();
        if (!editableCellStyle) {
            return undefined;
        }
        if (gridCell) {
            if (!this.adaptableApi.gridApi.isCellEditable(gridCell)) {
                return (0, StyleHelper_1.convertAdaptableStyleToCSS)(editableCellStyle);
            }
        }
        return undefined;
    }
    getEditableCellStyle(gridCell, params) {
        const editableCellStyle = this.adaptableApi.userInterfaceApi.getEditableCellStyle();
        if (!editableCellStyle) {
            return undefined;
        }
        if (gridCell) {
            if (this.adaptableApi.gridApi.isCellEditable(gridCell)) {
                return (0, StyleHelper_1.convertAdaptableStyleToCSS)(editableCellStyle);
            }
        }
        return undefined;
    }
    getEditedCellStyle(gridCell, params) {
        const editedCellStyle = this.adaptableApi.userInterfaceApi.getEditedCellStyle();
        if (!editedCellStyle) {
            return undefined;
        }
        if (gridCell) {
            if (this.adaptableApi.gridApi.isCellEdited(gridCell)) {
                return (0, StyleHelper_1.convertAdaptableStyleToCSS)(editedCellStyle);
            }
        }
        return undefined;
    }
    /**
     * The combination of styled column and format cells
     * This function decides when the two can be merged.
     */
    getFormatColumnAndStyledColumnCellStyle(column, params) {
        let styledColumn = this.adaptableApi.styledColumnApi.getStyledColumnForColumnId(column.columnId);
        let styledColumnStyle = {};
        if (styledColumn && !styledColumn?.IsSuspended) {
            const styledCellStyle = this.getStyledColumnStyle(styledColumn, column, params);
            // for percentbar we want to merge
            if (styledColumn.PercentBarStyle || styledColumn.BadgeStyle || styledColumn.GradientStyle) {
                styledColumnStyle = styledCellStyle;
            }
            else {
                // For other ones wo do not want to merge
                return styledCellStyle;
            }
        }
        const activeFormatColumnsWithStyle = this.adaptableApi.formatColumnApi.internalApi.getFormatColumnsWithStyleForColumn(column, {
            target: 'cell',
        });
        // background color of styledColumn.GradientStyle has precedence and wins over FormatColumn
        return {
            ...this.getFormatColumnCellStyle(column, activeFormatColumnsWithStyle, params),
            ...styledColumnStyle,
        };
    }
    getFormatColumnHeaderStyle(column, params) {
        if (params.columnGroup) {
            // FormatColumns are not supported in column groups
            // YET, see https://github.com/AdaptableTools/adaptable/issues/2947#issuecomment-3062304655
            return {};
        }
        const relevantFormatColumnsWithStyle = this.getRelevantFormatColumnHeaderStyles(column);
        if (!relevantFormatColumnsWithStyle.length) {
            return {};
        }
        return this.getFormatColumnAdaptableStyle(relevantFormatColumnsWithStyle);
    }
    getStyledColumnStyle(styledColumn, abColumn, params) {
        let style = {};
        const gradientStyle = styledColumn?.GradientStyle;
        if (params.value === undefined) {
            return;
        }
        let colValue = params.value;
        if (this.adaptableApi.gridApi.isGroupRowNode(params.node)) {
            return style;
            // if (styledColumn.IncludeGroupedRows) {
            //   const minColumnValue =
            //     this.adaptableApi.styledColumnApi.internalApi.getMinValueForNumericColumn(abColumn);
            //   const maxColumnValue =
            //     this.adaptableApi.styledColumnApi.internalApi.getMaxValueForNumericColumn(abColumn);
            //   /**
            //    * Color should always be in bounds, it should not overflow.
            //    * If the value is out of range, it shoul set the maximum/minimum color.
            //    */
            //   colValue = clamp(params.value, minColumnValue, maxColumnValue);
            // } else {
            //   return style;
            // }
        }
        if (styledColumn.BadgeStyle &&
            !styledColumn.BadgeStyle.RowScope?.ExcludeSummaryRows &&
            this.adaptableApi.gridApi.isSummaryNode(params?.node)) {
            return style;
        }
        if (gradientStyle) {
            const min = this.adaptableApi.styledColumnApi.internalApi.getNumericStyleMinValue(styledColumn, abColumn, params.node, colValue);
            const max = this.adaptableApi.styledColumnApi.internalApi.getNumericStyleMaxValue(styledColumn, abColumn, params.node, colValue);
            let cellBackColor;
            let reverseGradient = false;
            if (gradientStyle.ColumnComparison) {
                cellBackColor = gradientStyle.ColumnComparison.Color;
            }
            else {
                const matchingRange = this.adaptableApi.styledColumnApi.internalApi.findRangeForColumn(gradientStyle.CellRanges, abColumn, gradientStyle.RangeValueType, colValue);
                if (matchingRange) {
                    cellBackColor = matchingRange.Color;
                    reverseGradient = matchingRange.ReverseGradient;
                }
            }
            const increase = Math.abs(max - min);
            const percentage = ((colValue - min) / increase) * 100;
            let alpha = Number((percentage / 100).toPrecision(2));
            if (reverseGradient) {
                alpha = 1 - alpha;
            }
            const preparedColor = (0, StyleHelper_1.getVariableColor)(cellBackColor);
            // if no range match, do not apply color (black in this case)
            if (cellBackColor) {
                style.backgroundColor = (0, tinycolor2_1.default)(preparedColor).setAlpha(alpha).toRgbString();
            }
        }
        if (styledColumn.PercentBarStyle && styledColumn.PercentBarStyle.CellText) {
            style.paddingTop = 0;
            style.paddingBottom = 0;
        }
        return style;
    }
    getFormatColumnCellStyle(abColumn, activeFormatColumnsWithStyle, params) {
        if (!activeFormatColumnsWithStyle.length) {
            return {};
        }
        const relevantFormatColumnsWithStyle = activeFormatColumnsWithStyle.filter((formatColumn) => {
            return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value, 
            // @ts-ignore see #derived_pivot_cell_style
            params.__pivotResultColumn);
        });
        return this.getFormatColumnAdaptableStyle(relevantFormatColumnsWithStyle);
    }
    getFormatColumnAdaptableStyle(formatColumns) {
        // first has more precedence, then they need to be applied in reverse order
        return formatColumns.reduceRight((style, formatColumn) => {
            const formatColumnStyle = formatColumn.Style
                ? (0, StyleHelper_1.convertAdaptableStyleToCSS)(formatColumn.Style)
                : {};
            if (formatColumn.CellAlignment) {
                switch (formatColumn.CellAlignment) {
                    case 'Left':
                        style.textAlign = 'left';
                        break;
                    case 'Right':
                        style.textAlign = 'right';
                        break;
                    case 'Center':
                        style.textAlign = 'center';
                        break;
                }
            }
            return { ...style, ...formatColumnStyle };
        }, {});
    }
    getAlertCellStyle(gridCell, params) {
        const alert = this.adaptableApi.alertApi.internalApi.getAdaptableAlertWithHighlightCell(gridCell.column.columnId, params.node);
        if (alert) {
            const highlightCell = alert.alertDefinition.AlertProperties.HighlightCell;
            if (typeof highlightCell === 'object') {
                return (0, StyleHelper_1.convertAdaptableStyleToCSS)(highlightCell);
            }
            return {
                backgroundColor: UIHelper_1.default.getColorByMessageType(alert.alertDefinition.MessageType),
            };
        }
    }
    getFlashingCellStyle(gridCell, params) {
        const primaryKey = params.node.aggData ? params.node.id : gridCell.primaryKeyValue;
        const flashingCell = this.adaptableApi.flashingCellApi.internalApi.getAdaptableFlashingCellFor(primaryKey, gridCell.column.columnId);
        if (!flashingCell) {
            return {};
        }
        return (0, StyleHelper_1.convertAdaptableStyleToCSS)((flashingCell.direction === 'up'
            ? flashingCell.flashingCellDefinition.UpChangeStyle
            : flashingCell.direction === 'down'
                ? flashingCell.flashingCellDefinition.DownChangeStyle
                : flashingCell.flashingCellDefinition.NeutralChangeStyle) ?? {});
    }
    getCellHighlightStyle(gridCell, params) {
        const cellHightlight = this.adaptableApi.internalApi
            .getInternalState()
            .CellHighlightInfo.find((cellHighlightInfo) => {
            return (gridCell.column.columnId === cellHighlightInfo.columnId &&
                cellHighlightInfo.primaryKeyValue === gridCell.primaryKeyValue);
        });
        if (cellHightlight) {
            return (0, StyleHelper_1.convertAdaptableStyleToCSS)(cellHightlight.highlightStyle);
        }
    }
    isColGroupDef(columnDefinition) {
        // @ts-ignore
        return columnDefinition['children'] != null;
    }
    getRelevantFormatColumnHeaderStyles(column) {
        return this.adaptableApi.formatColumnApi.internalApi
            .getFormatColumnsWithStyleForColumn(column, {
            target: 'columnHeader',
        })
            .filter((formatColumn) => {
            return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInHeader(formatColumn, column);
        });
    }
}
exports.AgGridColumnAdapter = AgGridColumnAdapter;
