"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExportInternalApi = void 0;
const tslib_1 = require("tslib");
const ApiBase_1 = require("../Implementation/ApiBase");
const lodash_1 = require("lodash");
const tinycolor2_1 = tslib_1.__importDefault(require("tinycolor2"));
const Enums_1 = require("../../PredefinedConfig/Common/Enums");
const Uuid_1 = require("../../PredefinedConfig/Uuid");
const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
const ModuleConstants_1 = require("../../Utilities/Constants/ModuleConstants");
const ArrayExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/ArrayExtensions"));
const StringExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/StringExtensions"));
const FormatHelper_1 = tslib_1.__importStar(require("../../Utilities/Helpers/FormatHelper"));
const StyleHelper_1 = require("../../Utilities/Helpers/StyleHelper");
const ObjectFactory_1 = require("../../Utilities/ObjectFactory");
class ExportInternalApi extends ApiBase_1.ApiBase {
    constructor() {
        super(...arguments);
        this.excelStylesCache = {};
        this.cellClassKey2excelStyleIdMap = {};
        this.excelStylesWithFormattedDate = {};
    }
    isDataChangeInReport(cellDataChangedInfo, report) {
        // for All Data Report any data change is true so get out asap
        if (report.Name == 'All Data') {
            return true;
        }
        // if its a Custom Report then the User has to run it so we just ignore completely
        if (this.getExportApi().isExternalReport(report)) {
            return false;
        }
        // Start with the DataChanged Column and go through all possibilities
        switch (report.ReportColumnScope) {
            case 'AllColumns':
                // has to be relevant so continue to rows
                break;
            case 'ScopeColumns':
                // use the Scope object which will tell us if the Column is relevant
                if (!this.getColumnScopeApi().isColumnInScopeColumns(cellDataChangedInfo.column, report.Scope)) {
                    return false;
                }
                break;
            case 'SelectedColumns':
                let selectedCellInfo = this.getGridApi().getSelectedCellInfo();
                if (selectedCellInfo) {
                    if (selectedCellInfo.columns.find((c) => c.columnId == cellDataChangedInfo.column.columnId) == null) {
                        return false;
                    }
                }
                break;
            case 'VisibleColumns':
                //  hope that visibile column property is updated whenever the layout changes... (need to check!)
                if (!cellDataChangedInfo.column.visible) {
                    return false;
                }
                break;
        }
        // now do rows
        switch (report.ReportRowScope) {
            case 'AllRows':
                return true;
            case 'ExpressionRows':
                return true; // TODO this is the only difficult one - do we check AdapTableQL?  if we can then that is good as we can then do a delta after all...
            case 'SelectedCellRows':
                let selectedCellInfo = this.getGridApi().getSelectedCellInfo();
                if (selectedCellInfo && selectedCellInfo.gridCells) {
                    if (selectedCellInfo.gridCells.find((gc) => gc.primaryKeyValue == cellDataChangedInfo.primaryKeyValue)) {
                        return true;
                    }
                }
                return false;
            case 'SelectedRows':
                let selectedRowInfo = this.getGridApi().getSelectedRowInfo();
                if (selectedRowInfo && selectedRowInfo.gridRows) {
                    if (selectedRowInfo.gridRows.find((gr) => gr.primaryKeyValue == cellDataChangedInfo.primaryKeyValue)) {
                        return true;
                    }
                }
                return false;
            case 'VisibleRows':
                return this._adaptable.isRowNodeVisible(cellDataChangedInfo.rowNode);
        }
    }
    getExcelDataType(adaptableColumnType) {
        const mapColumnTypeToExcelType = (columnType) => {
            switch (columnType) {
                case 'abColDefNumber':
                    return 'Number';
                case 'abColDefBoolean':
                    return 'Boolean';
                case 'abColDefDate':
                    return 'DateTime';
                case 'abColDefString':
                default:
                    return 'String';
            }
        };
        if (Array.isArray(adaptableColumnType)) {
            const validColumnType = adaptableColumnType.find((colType) => colType.startsWith('abColDef'));
            if (!validColumnType) {
                return 'String';
            }
            return mapColumnTypeToExcelType(validColumnType);
        }
        else {
            return mapColumnTypeToExcelType(adaptableColumnType);
        }
    }
    isVisualDataExportInProgress() {
        return this.getAdaptableState().System.Export.visualDataExportInProgress;
    }
    isDateCellExportedAsFormattedValue(abColumn) {
        return (!!this.getExportOptions().exportDateFormat ||
            this.getCellExportFormatType(abColumn, 'Date') === 'formattedValue');
    }
    getCellExportFormatType(column, columnDataType) {
        const exportOptions = this.getExportOptions();
        const exportFormatType = exportOptions.exportFormatType;
        // First check if a function was provided and return the result
        if (exportFormatType != null && typeof exportFormatType === 'function') {
            const context = Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { column: column });
            return exportFormatType(context);
        }
        // Next Check if a "hard-coded" value has been provided and return that
        if (exportFormatType === 'rawValue') {
            return 'rawValue';
        }
        if (exportFormatType === 'formattedValue') {
            return 'formattedValue';
        }
        // Finally test if a DataType object has been provided and return the relevant property
        const dataFormatDataType = exportFormatType;
        if (dataFormatDataType) {
            // format is customized based on column data type
            switch (columnDataType) {
                case 'String':
                    return dataFormatDataType.string;
                case 'Number':
                    return dataFormatDataType.number;
                case 'Date':
                    return dataFormatDataType.date;
                default:
                    // default to rawValue for all other column types
                    return 'rawValue';
            }
        }
        return 'rawValue';
    }
    isDestinationEnabled(destination) {
        if (destination === 'Table' && this.getLayoutApi().internalApi.isLayoutGrouped()) {
            return false;
        }
        return true;
    }
    getExcelStylesForVisualDataExport(original_excelStyles) {
        return [];
    }
    getExcelStyleIdForCellClassKey(cellClassKey) {
        return this.cellClassKey2excelStyleIdMap[cellClassKey];
    }
    getExcelStyleWithFormattedDate(cellClassId) {
        return this.excelStylesWithFormattedDate[cellClassId];
    }
    createSystemReport(systemReportName) {
        switch (systemReportName) {
            case GeneralConstants_1.VISUAL_DATA_REPORT:
                return {
                    Uuid: (0, Uuid_1.createUuid)(),
                    Name: GeneralConstants_1.VISUAL_DATA_REPORT,
                    ReportColumnScope: 'VisibleColumns',
                    ReportRowScope: 'VisibleRows',
                    Query: undefined,
                    IsReadOnly: true,
                };
            case GeneralConstants_1.ALL_DATA_REPORT:
                return {
                    Uuid: (0, Uuid_1.createUuid)(),
                    Name: GeneralConstants_1.ALL_DATA_REPORT,
                    ReportColumnScope: 'AllColumns',
                    ReportRowScope: 'AllRows',
                    Query: undefined,
                    IsReadOnly: true,
                };
            case GeneralConstants_1.CURRENT_DATA_REPORT:
                return {
                    Uuid: (0, Uuid_1.createUuid)(),
                    Name: GeneralConstants_1.CURRENT_DATA_REPORT,
                    ReportColumnScope: 'VisibleColumns',
                    ReportRowScope: 'VisibleRows',
                    Query: undefined,
                    IsReadOnly: true,
                };
            case GeneralConstants_1.SELECTED_CELLS_REPORT:
                return {
                    Uuid: (0, Uuid_1.createUuid)(),
                    Name: GeneralConstants_1.SELECTED_CELLS_REPORT,
                    ReportColumnScope: 'SelectedColumns',
                    ReportRowScope: 'SelectedCellRows',
                    Query: undefined,
                    IsReadOnly: true,
                };
            case GeneralConstants_1.SELECTED_ROWS_REPORT:
                return {
                    Uuid: (0, Uuid_1.createUuid)(),
                    Name: GeneralConstants_1.SELECTED_ROWS_REPORT,
                    ReportColumnScope: 'VisibleColumns',
                    ReportRowScope: 'SelectedRows',
                    Query: undefined,
                    IsReadOnly: true,
                };
        }
    }
    isSystemReport(reportName) {
        return (reportName == null ||
            reportName == GeneralConstants_1.ALL_DATA_REPORT ||
            reportName == GeneralConstants_1.CURRENT_DATA_REPORT ||
            reportName == GeneralConstants_1.SELECTED_CELLS_REPORT ||
            reportName == GeneralConstants_1.SELECTED_ROWS_REPORT ||
            reportName == GeneralConstants_1.VISUAL_DATA_REPORT);
    }
    isSystemReportActive(reportName) {
        if (reportName == GeneralConstants_1.SELECTED_CELLS_REPORT) {
            return this.getGridApi().isGridRangeSelectable();
        }
        if (reportName == GeneralConstants_1.SELECTED_ROWS_REPORT) {
            return this.getGridApi().isGridRowSelectable();
        }
        if (reportName === GeneralConstants_1.VISUAL_DATA_REPORT) {
            return this.getAdaptableApi()
                .exportApi.getAvailableExportDestinations()
                .includes(Enums_1.ExportDestination.Excel);
        }
        return true;
    }
    isSystemExportDestinationActive(exportDestination) {
        if (exportDestination === Enums_1.ExportDestination.Excel) {
            return this.getExportApi().canExportToExcel();
        }
        return true;
    }
    getReportColumnScopeShortDescription(report) {
        var _a, _b;
        if (this.getExportApi().isExternalReport(report)) {
            return ['[Custom Columns]'];
        }
        switch (report.ReportColumnScope) {
            case 'AllColumns':
                return ['[All Columns]'];
            case 'VisibleColumns':
                return ['[Visible Columns]'];
            case 'SelectedColumns':
                return ['[Selected Columns]'];
            case 'ScopeColumns':
                if ('ColumnIds' in (report === null || report === void 0 ? void 0 : report.Scope)) {
                    return (_b = (_a = report.Scope.ColumnIds).map) === null || _b === void 0 ? void 0 : _b.call(_a, (columnId) => { var _a; return (_a = this.getColumnApi().getFriendlyNameForColumnId(columnId)) !== null && _a !== void 0 ? _a : columnId; });
                }
                return ['[Bespoke Columns]'];
        }
    }
    getReportColumnScopeLongDescription(report) {
        if (this.getExportApi().isExternalReport(report)) {
            return '[Custom Columns]';
        }
        switch (report.ReportColumnScope) {
            case 'AllColumns':
                return '[All Columns]';
            case 'VisibleColumns':
                return '[Visible Columns]';
            case 'SelectedColumns':
                return '[Selected Columns]';
            case 'ScopeColumns':
                return this.getColumnScopeApi().getScopeDescription(report.Scope);
        }
    }
    getReportExpressionDescription(report, cols) {
        if (this.getExportApi().isExternalReport(report)) {
            return '[Custom Data]';
        }
        if (this.isSystemReport(report.Name)) {
            if (report.Name == GeneralConstants_1.ALL_DATA_REPORT) {
                return '[All Data]';
            }
            else if (report.Name == GeneralConstants_1.CURRENT_DATA_REPORT) {
                return '[All Current Data]';
            }
            else if (report.Name == GeneralConstants_1.SELECTED_CELLS_REPORT) {
                return '[Selected Cells Data]';
            }
            else if (report.Name == GeneralConstants_1.SELECTED_ROWS_REPORT) {
                return '[Selected Rows Data]';
            }
            else if (report.Name == GeneralConstants_1.VISUAL_DATA_REPORT) {
                return '[Current Data as WYSIWYG]';
            }
        }
        else {
            switch (report.ReportRowScope) {
                case 'AllRows':
                    return '[All Rows]';
                case 'VisibleRows':
                    return '[Visible Rows]';
                case 'SelectedRows':
                    return '[Selected Rows]';
                case 'ExpressionRows':
                    return this.getAdaptableInternalApi().getAdaptableQueryExpressionText(report.Query);
            }
        }
    }
    getReportDataColumns(report, includePrimaryKey = false) {
        let reportColumns = [];
        let gridColumns = this.getColumnApi().getExportableColumns();
        if (this.getExportApi().isExternalReport(report)) {
            return reportColumns;
        }
        // first get the cols depending on the Column Scope
        switch (report.ReportColumnScope) {
            case 'AllColumns':
                reportColumns = gridColumns;
                break;
            case 'VisibleColumns':
                reportColumns = gridColumns.filter((c) => c.visible);
                break;
            case 'SelectedColumns':
                // we extract the selected columns from the grid columns to preserve the grid column order
                const selectedColumnIds = this.getAdaptableApi()
                    .gridApi.getSelectedCellInfo()
                    .columns.map((column) => column.columnId);
                reportColumns = gridColumns.filter((gridColumn) => selectedColumnIds.includes(gridColumn.columnId));
                break;
            case 'ScopeColumns':
                if ('ColumnIds' in report.Scope) {
                    reportColumns = report.Scope.ColumnIds.map((columnId) => this.getColumnApi().getColumnWithColumnId(columnId)).filter((c) => c);
                }
                else {
                    reportColumns = this.getColumnScopeApi().getColumnsForScope(report.Scope);
                }
                break;
        }
        if (includePrimaryKey) {
            const pkColumn = reportColumns.find((column) => column.columnId === this.getAdaptableApi().optionsApi.getPrimaryKey());
            // TODO simplify after we fix the IsPrimaryKey bug
            // const pkColumn = reportColumns.find(column => column.IsPrimaryKey);
            if (!pkColumn && !!this.getColumnApi().getPrimaryKeyColumn()) {
                reportColumns.push(this.getColumnApi().getPrimaryKeyColumn());
            }
        }
        return reportColumns.map((column) => {
            var _a;
            return ({
                columnId: column.columnId,
                friendlyName: column.friendlyName,
                dataType: column.dataType,
                field: (_a = column.field) !== null && _a !== void 0 ? _a : column.columnId,
            });
        });
    }
    getReportDataRows(report, columns, includePrimaryKey) {
        var _a, _b;
        if (ArrayExtensions_1.default.IsNullOrEmpty(columns)) {
            return [];
        }
        const columnIds = columns.map((column) => column.columnId);
        const resultRowData = [];
        switch (report.ReportRowScope) {
            case 'AllRows':
                this.getAdaptableInternalApi().forAllRowNodesDo((rowNode) => {
                    resultRowData.push(this.getRowObjectForColumnIds(rowNode, columnIds, report.Name));
                });
                break;
            case 'VisibleRows':
                this.getAdaptableInternalApi().forAllVisibleRowNodesDo((rowNode) => {
                    resultRowData.push(this.getRowObjectForColumnIds(rowNode, columnIds, report.Name));
                });
                break;
            case 'ExpressionRows':
                this.getAdaptableInternalApi().forAllRowNodesDo((rowNode) => {
                    var _a;
                    if (this.getAdaptableApi()
                        .internalApi.getQueryLanguageService()
                        .evaluateBooleanExpression((_a = report.Query) === null || _a === void 0 ? void 0 : _a.BooleanExpression, ModuleConstants_1.ExportModuleId, rowNode)) {
                        resultRowData.push(this.getRowObjectForColumnIds(rowNode, columnIds, report.Name));
                    }
                });
                break;
            case 'SelectedCellRows':
                const selectedCellInfo = this.getGridApi().getSelectedCellInfo();
                const { gridCells: GridCells } = selectedCellInfo;
                let selectedCellsByPrimaryKey = (0, lodash_1.groupBy)(GridCells, 'primaryKeyValue');
                // we iterate over all visibleRowNodes to preserve the current order
                this.getAdaptableInternalApi().forAllVisibleRowNodesDo((rowNode) => {
                    const rowPrimaryKeyValue = this.getGridApi().getPrimaryKeyValueForRowNode(rowNode);
                    const selectedRowCells = selectedCellsByPrimaryKey[rowPrimaryKeyValue];
                    if (selectedRowCells) {
                        const selectedRowColumnIds = selectedRowCells.map((rowCell) => rowCell.column.columnId);
                        const selectedColumnIds = columnIds.filter((columnId) => selectedRowColumnIds.includes(columnId));
                        const row = this.getRowObjectForColumnIds(rowNode, selectedColumnIds, report.Name);
                        if (includePrimaryKey) {
                            row[this.getAdaptableApi().optionsApi.getPrimaryKey()] = rowPrimaryKeyValue;
                        }
                        resultRowData.push(row);
                    }
                });
                break;
            case 'SelectedRows':
                const selectedRowInfo = this.getGridApi().getSelectedRowInfo();
                const selectedGridRowPrimaryKeys = (_b = (_a = selectedRowInfo === null || selectedRowInfo === void 0 ? void 0 : selectedRowInfo.gridRows) === null || _a === void 0 ? void 0 : _a.filter((gr) => gr.rowInfo.isGroup == false).map((gridRow) => gridRow.primaryKeyValue)) !== null && _b !== void 0 ? _b : [];
                if (selectedGridRowPrimaryKeys.length) {
                    this.getAdaptableInternalApi().forAllRowNodesDo((rowNode) => {
                        const rowPrimaryKeyValue = this.getGridApi().getPrimaryKeyValueForRowNode(rowNode);
                        if (selectedGridRowPrimaryKeys.includes(rowPrimaryKeyValue)) {
                            resultRowData.push(this.getRowObjectForColumnIds(rowNode, columnIds, report.Name));
                        }
                    });
                }
                break;
        }
        return resultRowData;
    }
    getReportData(report, includePrimaryKey = false) {
        if (this.getExportApi().isExternalReport(report)) {
            return this.getExportApi().runExternalReport(report.Name);
        }
        const columns = this.getReportDataColumns(report, includePrimaryKey);
        const rows = this.getReportDataRows(report, columns, includePrimaryKey);
        return { columns, rows };
    }
    getReportDataAsArray(report, includePrimaryKey = false) {
        const reportData = this.getReportData(report, includePrimaryKey);
        return this.convertReportDataToArray(reportData);
    }
    convertReportDataToArray(reportData) {
        return [
            reportData.columns.map((column) => column.friendlyName),
            ...reportData.rows.map((row) => reportData.columns.map((column) => row[column.columnId])),
        ];
    }
    getRowObjectForColumnIds(rowNode, columnIds, reportName) {
        return columnIds.reduce((result, columnId) => {
            result[columnId] = this.getCellExportValueFromRowNode(rowNode, columnId, reportName);
            return result;
        }, {});
    }
    publishLiveLiveDataChangedEvent(reportDestination, liveDataTrigger, liveReport) {
        const liveDataChangedInfo = Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { reportDestination: reportDestination, liveDataTrigger: liveDataTrigger, liveReport: liveReport });
        this.getEventApi().emit('LiveDataChanged', liveDataChangedInfo);
    }
    getCellExportValueFromRowNode(rowNode, columnId, reportName) {
        return this.getCellExportValueFromRawValue(rowNode, this.getGridApi().getRawValueFromRowNode(rowNode, columnId), columnId, reportName);
    }
    getCellExportValueFromRawValue(rowNode, cellRawValue, columnId, reportName) {
        if (StringExtensions_1.default.IsNullOrEmpty(cellRawValue)) {
            return cellRawValue;
        }
        const column = this.getColumnApi().getColumnWithColumnId(columnId);
        const columnDataType = column.dataType;
        // 1. if it is a Visual Data report then we always ONLY send the formatted value and ignore all other properties
        if (reportName == GeneralConstants_1.VISUAL_DATA_REPORT) {
            return this.getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, 'formattedValue');
        }
        // 2. if this is a date column and there is a custom export date format provided, that will next take precedence
        if (columnDataType === 'Date' && !!this.getCustomExportDateFormat()) {
            const exportDateFormat = this.getCustomExportDateFormat();
            return FormatHelper_1.default.DateFormatter(cellRawValue, {
                Pattern: exportDateFormat,
            });
        }
        // 3. in all other cases check the general export format types
        const cellExportFormat = this.getExportApi().internalApi.getCellExportFormatType(column, columnDataType);
        return this.getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, cellExportFormat);
    }
    getReportFileName(reportName, destination) {
        let fileName;
        const reportFilename = this.getExportOptions().reportFilename;
        if (reportFilename) {
            const reportFileNameContext = Object.assign(Object.assign({}, (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi())), { reportName,
                destination });
            fileName = reportFilename(reportFileNameContext);
        }
        else {
            fileName = StringExtensions_1.default.ReplaceEmptySpacesWithUnderscore(reportName);
            if (this.getExportOptions().appendFileTimestamp) {
                fileName = `${fileName}_${(0, FormatHelper_1.DateFormatter)(new Date(), {
                    Pattern: 'yyyyMMdd_HHmmss',
                })}`;
            }
        }
        return fileName;
    }
    getCustomExportDateFormat() {
        return this.getExportOptions().exportDateFormat;
    }
    getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, 
    // default to rawValue if, for some reason, the configs provide invalid values
    type = 'rawValue') {
        return type === 'rawValue'
            ? cellRawValue
            : // type === formattedValue
                this.getGridApi().getDisplayValueFromRawValue(rowNode, columnId, cellRawValue);
    }
    // aggregate and merge all acive Adaptable styles with the user proviided ExcelStyles
    buildExcelStylesForVisualReports() {
        // for historical reasons, the styles are merged as class variables
        // we could/should refactor this to be more functional
        this.createExcelStyleMemoization();
        return Object.values(this.excelStylesCache);
    }
    createExcelStyleMemoization() {
        this.resetExcelStyleMemoization();
        // we memoize as much as possible, as this is called quite A LOT
        const adaptableColumnMap = {};
        const getAdaptableColumnWithColumnId = (columnId) => {
            const memoizedColumn = adaptableColumnMap[columnId];
            if (memoizedColumn) {
                return memoizedColumn;
            }
            const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
            adaptableColumnMap[columnId] = abColumn;
            return abColumn;
        };
        const formatColumnsWithDisplayFormatForColumn = {};
        const getFormatColumnsWithDisplayFormatForColumn = (columnId) => {
            const memoizedFormatColumns = formatColumnsWithDisplayFormatForColumn[columnId];
            if (memoizedFormatColumns) {
                return memoizedFormatColumns;
            }
            const abColumn = getAdaptableColumnWithColumnId(columnId);
            const formatColumns = this.getAdaptableApi().formatColumnApi.internalApi.getFormatColumnsWithDisplayFormatForColumn(abColumn);
            formatColumnsWithDisplayFormatForColumn[columnId] = formatColumns;
            return formatColumns;
        };
        const agGridDisplayedColumns = this.getAgGridApi().getAllDisplayedColumns();
        const colDefs = agGridDisplayedColumns.map((column) => {
            return column.getColDef();
        });
        const forAllVisibleRowNodesDoConfig = { includeGroupRows: true };
        const agGridApi = this.getAgGridApi();
        const userExcelStyles = this.getAdaptableInternalApi().getAgGridAdapter().getUserGridOptionsProperty('excelStyles') ||
            [];
        this.getAdaptableInternalApi().forAllVisibleRowNodesDo((node, rowIndex) => {
            const rowParams = {
                node,
                data: node.data,
                rowIndex,
                api: agGridApi,
                context: agGridApi.getGridOption('context') || {},
            };
            const getRowStyleFn = agGridApi.getGridOption('getRowStyle');
            const rowStyle = getRowStyleFn ? getRowStyleFn(rowParams) : {};
            agGridDisplayedColumns.forEach((column, columnIndex) => {
                var _a, _b, _c;
                const colDef = colDefs[columnIndex];
                const columnId = column.getId();
                const adaptableColumn = this.getColumnApi().getColumnWithColumnId(columnId);
                const isDateCellExportedAsFormattedValue = this.isDateCellExportedAsFormattedValue(adaptableColumn);
                let cellClassParams;
                const getLazyCellClassParams = () => {
                    if (!cellClassParams) {
                        cellClassParams = {
                            colDef,
                            node,
                            column,
                            data: node.data,
                            value: this.getGridApi().getRawValueFromRowNode(node, columnId),
                            rowIndex,
                            api: agGridApi,
                            context: {},
                        };
                    }
                    return cellClassParams;
                };
                const cellStyle = typeof colDef.cellStyle === 'function' ? colDef.cellStyle(getLazyCellClassParams()) : {};
                const excelStyles = [];
                // add user defined excel styles
                let userColDefCellClass = this._adaptable.agGridColumnAdapter.getUserColDefProperty(column.getColId(), 'cellClass');
                const userDefinedCellClass = typeof userColDefCellClass === 'function'
                    ? userColDefCellClass(getLazyCellClassParams())
                    : userColDefCellClass;
                const userDefinedExcelStyle = userDefinedCellClass &&
                    userExcelStyles.find((excelStyle) => {
                        var _a;
                        return typeof userDefinedCellClass === 'string'
                            ? userDefinedCellClass === excelStyle.id
                            : (_a = userDefinedCellClass === null || userDefinedCellClass === void 0 ? void 0 : userDefinedCellClass.includes) === null || _a === void 0 ? void 0 : _a.call(userDefinedCellClass, excelStyle.id);
                    });
                if (userDefinedExcelStyle) {
                    excelStyles.push(userDefinedExcelStyle);
                }
                // add adaptable derived styles (format column etc.)
                const adaptableStyle = Object.assign(Object.assign({}, rowStyle), Object.keys(cellStyle).reduce((result, key) => {
                    if (cellStyle[key] !== null) {
                        result[key] = cellStyle[key];
                    }
                    return result;
                }, {}));
                const sanitizedAdaptableStyle = (0, StyleHelper_1.sanitizeStyle)(adaptableStyle);
                if (Object.values(sanitizedAdaptableStyle).some((style) => style != null)) {
                    excelStyles.push(this.convertCSSToExcelStyle(sanitizedAdaptableStyle));
                }
                const excelDataType = this.getExcelDataType(colDef === null || colDef === void 0 ? void 0 : colDef.type);
                const rawValue = this.getGridApi().getRawValueFromRowNode(node, column.getId());
                // don't add the cell style if it has no adaptable custom styles
                if (!excelStyles.length &&
                    // if this is a formatted Date value, we still need to add the AG GRID specific type & numberFormat below
                    !(excelDataType === 'DateTime' && isDateCellExportedAsFormattedValue)) {
                    return;
                }
                const cellClassId = this._adaptable.agGridColumnAdapter.getExcelClassNameForCell(column.getId(), this._adaptable.getPrimaryKeyValueFromRowNode(node), userDefinedCellClass);
                const finalCellExcelStyle = Object.assign({}, ...excelStyles);
                if (excelDataType === 'DateTime' && isDateCellExportedAsFormattedValue) {
                    let dateFormatPattern = this.getExportOptions().exportDateFormat;
                    const abColumn = getAdaptableColumnWithColumnId(column.getColId());
                    if (!dateFormatPattern) {
                        const mostRelevantFormatColumn = this.getAdaptableApi().formatColumnApi.internalApi.getMostRelevantFormatColumnForColumn(getFormatColumnsWithDisplayFormatForColumn(column.getColId()), abColumn, { node, value: rawValue });
                        dateFormatPattern =
                            ((_a = mostRelevantFormatColumn === null || mostRelevantFormatColumn === void 0 ? void 0 : mostRelevantFormatColumn.DisplayFormat) === null || _a === void 0 ? void 0 : _a.Formatter) === 'DateFormatter' &&
                                ((_c = (_b = mostRelevantFormatColumn === null || mostRelevantFormatColumn === void 0 ? void 0 : mostRelevantFormatColumn.DisplayFormat) === null || _b === void 0 ? void 0 : _b.Options) === null || _c === void 0 ? void 0 : _c.Pattern);
                    }
                    if (dateFormatPattern) {
                        const normalisedValue = this._adaptable.getNormalisedValueFromRawValue(rawValue, abColumn);
                        if (normalisedValue) {
                            // we have to pass the date in the ISO format to Excel
                            // see https://www.ag-grid.com/javascript-data-grid/excel-export-data-types/#dates
                            // we can NOT use Date.toISOString() because we don't want the timezone corrections to kick in
                            const isoFormattedValue = (0, FormatHelper_1.DateFormatter)(normalisedValue, {
                                Pattern: `yyyy-MM-dd'T'HH:mm:ss.SSS`,
                            });
                            if (isoFormattedValue) {
                                finalCellExcelStyle.dataType = 'DateTime';
                                finalCellExcelStyle.numberFormat = { format: dateFormatPattern };
                                // create a new cell key to ensure any user provided className does not interfere
                                const cellKey = this._adaptable.agGridColumnAdapter.getExcelClassNameForCell(column.getColId(), this._adaptable.getPrimaryKeyValueFromRowNode(node));
                                // we need to register so that later the cellProcessor will put the isoFormattedValue through (thus giving the formatting responsability to Excel)
                                this.registerExcelStyleWithFormattedDate(cellKey, isoFormattedValue);
                            }
                        }
                    }
                }
                this.registerExcelStyle(finalCellExcelStyle, cellClassId);
            });
        }, forAllVisibleRowNodesDoConfig);
    }
    convertCSSToExcelStyle(style) {
        const getHexColor = (color) => {
            const preparedColor = (0, StyleHelper_1.getVariableColor)(color);
            const t = (0, tinycolor2_1.default)(preparedColor);
            const a = t.getAlpha();
            return tinycolor2_1.default.mix((0, tinycolor2_1.default)('white'), t, a * 100).toHexString();
        };
        let result = {};
        if (style.backgroundColor != null) {
            result.interior = {
                color: getHexColor(style.backgroundColor),
                pattern: 'Solid',
            };
        }
        if (style.borderColor != null) {
            const excelBorder = {
                color: style.borderColor,
                lineStyle: 'Continuous',
                weight: 1,
            };
            result.borders = {
                borderBottom: excelBorder,
                borderLeft: excelBorder,
                borderRight: excelBorder,
                borderTop: excelBorder,
            };
        }
        if (style.textAlign) {
            result.alignment = {
                horizontal: StringExtensions_1.default.CapitaliseFirstLetter(style.textAlign),
            };
        }
        if (style.color != null) {
            if (!result.font) {
                result.font = {};
            }
            result.font = {
                color: getHexColor(style.color),
            };
        }
        if (style.fontStyle === 'italic') {
            if (!result.font) {
                result.font = {};
            }
            result.font.italic = true;
        }
        if (style.fontWeight != null &&
            (style.fontWeight === 'bold' || Number(style.fontWeight) >= 600)) {
            if (!result.font) {
                result.font = {};
            }
            result.font.bold = true;
        }
        if (style.fontSize != null) {
            if (!result.font) {
                result.font = {};
            }
            result.font.size = (0, StyleHelper_1.convertCSSAbsoluteFontSizeToPt)(style.fontSize);
        }
        return result;
    }
    resetExcelStyleMemoization() {
        this.excelStylesCache = {};
        this.cellClassKey2excelStyleIdMap = {};
        this.excelStylesWithFormattedDate = {};
    }
    registerExcelStyle(excelStyle, cellClassKey) {
        const excelStyleKey = JSON.stringify(excelStyle);
        if (!this.excelStylesCache[excelStyleKey]) {
            const excelStyleId = (0, Uuid_1.createUuid)();
            const excelStyleWithId = Object.assign(Object.assign({}, excelStyle), { id: excelStyleId });
            this.excelStylesCache[excelStyleKey] = excelStyleWithId;
        }
        this.cellClassKey2excelStyleIdMap[cellClassKey] = this.excelStylesCache[excelStyleKey].id;
    }
    registerExcelStyleWithFormattedDate(cellClassId, isoFormattedValue) {
        this.excelStylesWithFormattedDate[cellClassId] = isoFormattedValue;
    }
}
exports.ExportInternalApi = ExportInternalApi;
