"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CellSummaryModule = void 0;
const tslib_1 = require("tslib");
const ModuleConstants = tslib_1.__importStar(require("../Utilities/Constants/ModuleConstants"));
const ArrayExtensions_1 = require("../Utilities/Extensions/ArrayExtensions");
const ObjectFactory_1 = tslib_1.__importDefault(require("../Utilities/ObjectFactory"));
const AggregatedScalarLiveValue_1 = require("../Utilities/Services/AggregatedScalarLiveValue");
const CellSummaryStatusPanel_1 = require("../View/CellSummary/CellSummaryStatusPanel");
const AdaptableModuleBase_1 = require("./AdaptableModuleBase");
/**
 * Module that provides Cell Summaries on numeric columns
 */
class CellSummaryModule extends AdaptableModuleBase_1.AdaptableModuleBase {
    constructor(api) {
        super(ModuleConstants.CellSummaryModuleId, ModuleConstants.CellSummaryFriendlyName, 'cells', 'CellSummaryPopup', 'See summary information on a group of numeric cells using multiple summary operations', api);
        this.cachedCellSummary = new WeakMap();
    }
    getViewAccessLevel() {
        return 'Full';
    }
    createColumnMenuItems(column) {
        if (!this.isModuleAvailable()) {
            return;
        }
        if (column.dataType !== 'number') {
            return;
        }
        return [
            this.createMainMenuItemShowPopup({
                Name: 'cell-summary-show',
                Label: 'See Cell Summary',
                ComponentName: this.moduleInfo.Popup,
                Icon: this.moduleInfo.Glyph,
                PopupParams: {
                    source: 'ColumnMenu',
                    column,
                },
            }),
        ];
    }
    createContextMenuItems(menuContext) {
        if (!this.isModuleAvailable()) {
            return;
        }
        if (menuContext.adaptableColumn &&
            menuContext.isSelectedCell &&
            menuContext.adaptableColumn.dataType === 'number') {
            return [
                this.createMainMenuItemShowPopup({
                    Name: 'cell-summary-show',
                    Label: 'See Cell Summary',
                    ComponentName: this.moduleInfo.Popup,
                    Icon: this.moduleInfo.Glyph,
                    PopupParams: {
                        source: 'ContextMenu',
                    },
                }),
            ];
        }
    }
    createCellSummaryInfo(selectedCellInfo) {
        if (this.cachedCellSummary.has(selectedCellInfo)) {
            return this.cachedCellSummary.get(selectedCellInfo);
        }
        let selectedCellSummary = ObjectFactory_1.default.CreateEmptyCellSummmary();
        if (selectedCellInfo && ArrayExtensions_1.ArrayExtensions.hasOneItem(selectedCellInfo.columns)) {
            let selectedColumn = selectedCellInfo.columns[0];
            if (selectedColumn && selectedColumn.dataType === 'number') {
                const numberFormatOptions = this.getNumberFormatOptions(selectedColumn);
                const rowNodes = selectedCellInfo.gridCells.map((gc) => gc.rowNode);
                const handleExpression = (functionName) => {
                    const aggScalarValue = new AggregatedScalarLiveValue_1.AggregatedScalarLiveValue({
                        aggregatedScalarExpression: `${functionName}([${selectedColumn.columnId}])`,
                    }, ModuleConstants.CellSummaryModuleId, this.api, () => rowNodes);
                    return this.formatValue(numberFormatOptions, selectedColumn, aggScalarValue.getGlobalAggregatedValue(), rowNodes[0]);
                };
                const sumValue = handleExpression('SUM');
                const avgValue = handleExpression('AVG');
                const modeValue = handleExpression('MODE');
                const medianValue = handleExpression('MEDIAN');
                const distinctValue = handleExpression('DISTINCT');
                const maxValue = handleExpression('MAX');
                const minValue = handleExpression('MIN');
                const countValue = selectedCellInfo.gridCells.length;
                const stdDeviation = handleExpression('STD_DEVIATION');
                selectedCellSummary = {
                    Sum: sumValue,
                    Average: avgValue,
                    Median: medianValue,
                    Mode: modeValue,
                    Distinct: distinctValue,
                    Max: maxValue,
                    Min: minValue,
                    Count: countValue,
                    Std_Deviation: stdDeviation,
                    Only: distinctValue == 1 ? JSON.stringify(selectedCellInfo.gridCells[0].rawValue) : undefined,
                };
                const weightedAverageConfig = this.getWeightedAverageConfig(selectedColumn.columnId);
                if (weightedAverageConfig) {
                    const weightedAverage = this.getWeightedAverageCellSummary(weightedAverageConfig, selectedColumn.columnId, rowNodes);
                    if (weightedAverage !== null) {
                        selectedCellSummary.Weighted_Average = this.formatValue(numberFormatOptions, selectedColumn, weightedAverage, rowNodes[0]);
                    }
                }
                const customCellSummaryOperations = this.api.cellSummaryApi.getCustomCellSummaryOperations();
                customCellSummaryOperations?.forEach((operation) => {
                    if (operation.operationFunction) {
                        const cellSummaryOperationContext = {
                            selectedCellInfo,
                            selectedColumn,
                            ...this.api.internalApi.buildBaseContext(),
                        };
                        selectedCellSummary[operation.operationName] = operation.operationFunction(cellSummaryOperationContext);
                    }
                });
                this.cachedCellSummary.set(selectedCellInfo, selectedCellSummary);
            }
        }
        return selectedCellSummary;
    }
    getNumberFormatOptions(column) {
        let columnToFormat = column;
        let adaptableFormat;
        // first get any Display Formats applied for the column and if provided, then return those
        // note: this will automatically include any custom formats
        adaptableFormat = this.api.formatColumnApi.getDisplayFormatForColumn(columnToFormat);
        if (adaptableFormat) {
            return adaptableFormat.Options;
        }
        // temporary hack until we get the parent for pivot columns - just in case we dont have time...
        if (columnToFormat.isGeneratedPivotResultColumn) {
            const parts = columnToFormat.columnId.split('_');
            const colid = parts[parts.length - 1];
            columnToFormat = this.api.columnApi.getColumnWithColumnId(colid);
            // check if this pivot result column has been give its own Format and if so return it
            adaptableFormat = this.api.formatColumnApi.getDisplayFormatForColumn(columnToFormat);
            if (adaptableFormat) {
                return adaptableFormat.Options;
            }
        }
        // otherwise get the numeric format in Cell Summary Options (either function or value)
        const numericDisplayFormat = this.api.optionsApi.getCellSummaryOptions().numericDisplayFormat;
        if (typeof numericDisplayFormat === 'function') {
            const context = {
                column: columnToFormat,
                ...this.api.internalApi.buildBaseContext(),
            };
            return numericDisplayFormat(context);
        }
        else {
            return numericDisplayFormat;
        }
    }
    formatValue(formatterOptions, column, valueToFormat, node) {
        return isNaN(valueToFormat)
            ? valueToFormat
            : this.api.formatColumnApi.internalApi.getNumberFormattedValue(valueToFormat, node, column, formatterOptions);
    }
    getWeightedAverageConfig(columnId) {
        const weightedAverageConfig = (this.api.layoutApi.getCurrentLayout().TableAggregationColumns || []).find(({ ColumnId, AggFunc }) => typeof AggFunc === 'object' && AggFunc.type === 'weightedAverage' && ColumnId === columnId);
        return weightedAverageConfig;
    }
    getWeightedAverageCellSummary(weightedAverageConfig, columnId, rowNodes) {
        const weightedColumnId = weightedAverageConfig.AggFunc
            .weightedColumnId;
        const expression = `AVG([${columnId}], WEIGHT([${weightedColumnId}]))`;
        const aggScalarValue = new AggregatedScalarLiveValue_1.AggregatedScalarLiveValue({
            aggregatedScalarExpression: expression,
        }, ModuleConstants.CellSummaryModuleId, this.api, () => rowNodes);
        return aggScalarValue.getGlobalAggregatedValue();
    }
    getViewProperties() {
        return {
            getStatusBarPanelProps() {
                /**
                 * This uses a custom view because it has special logic to
                 * trigger summary operations when the component is rendered.
                 */
                return {
                    view: CellSummaryStatusPanel_1.CellSummaryStatusPanel,
                };
            },
        };
    }
}
exports.CellSummaryModule = CellSummaryModule;
