import { CalculatedColumnModuleId } from '../Constants/ModuleConstants';
import { AggregatedScalarLiveValue } from './AggregatedScalarLiveValue';
export class CalculatedColumnExpressionService {
    adaptableApi;
    aggregatedScalarLiveValuesMap = new Map();
    constructor(adaptableApi) {
        this.adaptableApi = adaptableApi;
        this.adaptableApi = adaptableApi;
    }
    listentoCellDataChange(cellDataChangedInfo) {
        const refreshedCalculatedColumns = [];
        this.aggregatedScalarLiveValuesMap.forEach((aggregatedScalarLiveValue, calculatedColumnId) => {
            const calculatedColumn = this.adaptableApi.calculatedColumnApi.getCalculatedColumnById(calculatedColumnId);
            const columnDependencies = this.adaptableApi.calculatedColumnApi.internalApi.getReferencedColumnIdsForCalculatedColumn(calculatedColumn);
            if (columnDependencies.includes(cellDataChangedInfo.column.columnId)) {
                aggregatedScalarLiveValue.refresh();
                refreshedCalculatedColumns.push(calculatedColumn.ColumnId);
            }
        });
        if (refreshedCalculatedColumns.length) {
            this.adaptableApi.gridApi.refreshColumns(refreshedCalculatedColumns);
        }
    }
    listentoRowDataChange(rowDataChangedInfo) {
        const refreshedCalculatedColumns = [];
        this.aggregatedScalarLiveValuesMap.forEach((aggregatedScalarLiveValue, calculatedColumnId) => {
            const calculatedColumn = this.adaptableApi.calculatedColumnApi.getCalculatedColumnById(calculatedColumnId);
            aggregatedScalarLiveValue.refresh();
            refreshedCalculatedColumns.push(calculatedColumn.ColumnId);
        });
        if (refreshedCalculatedColumns.length) {
            this.adaptableApi.gridApi.refreshColumns(refreshedCalculatedColumns);
        }
    }
    destroy() {
        this.aggregatedScalarLiveValuesMap.clear();
        this.aggregatedScalarLiveValuesMap = null;
    }
    getCalculatedColumnDataType(calculatedColumnQuery) {
        try {
            if (calculatedColumnQuery.AggregatedScalarExpression) {
                // currently AggregatedScalarExpression support only numerical values
                // TODO AFL try to derive the type from the aggregatedColumn?
                // we definitely don't want to aggregate everything only to get the data type
                return 'number';
            }
            let firstRowNode = this.adaptableApi.gridApi.getFirstRowNode();
            let firstRowValue = this.adaptableApi.internalApi
                .getQueryLanguageService()
                .evaluateScalarExpression(calculatedColumnQuery.ScalarExpression, CalculatedColumnModuleId, firstRowNode);
            if (firstRowValue instanceof Date) {
                return 'date';
            }
            if (typeof firstRowValue === 'boolean') {
                return 'boolean';
            }
            if (typeof firstRowValue === 'string') {
                return 'text';
            }
            if (typeof firstRowValue === 'number') {
                return 'number';
            }
            if (Array.isArray(firstRowValue)) {
                return 'numberArray';
            }
        }
        catch (e) {
            this.adaptableApi.logError(`Invalid CalculatedColumn expression ${this.adaptableApi.expressionApi.getAdaptableQueryExpression(calculatedColumnQuery)} :: ${e}`);
            return 'number';
        }
    }
    isCalculatedColumnQueryValid(calculatedColumnQuery) {
        if (calculatedColumnQuery.ScalarExpression) {
            try {
                // TODO AFL add a cached validation for ScalarExpression, just like for all the other types
                let firstRowNode = this.adaptableApi.gridApi.getFirstRowNode();
                this.adaptableApi.internalApi
                    .getQueryLanguageService()
                    .evaluateScalarExpression(calculatedColumnQuery.ScalarExpression, CalculatedColumnModuleId, firstRowNode);
                return true;
            }
            catch (e) {
                // no logging as this method is used only in the UI
                return false;
            }
        }
        if (calculatedColumnQuery.AggregatedScalarExpression) {
            const validationResult = this.adaptableApi.expressionApi.isValidAggregatedScalarExpression(calculatedColumnQuery.AggregatedScalarExpression, CalculatedColumnModuleId);
            return validationResult;
        }
        // if query has neither a ScalarExpression nor an AggregatedScalarExpression => it can only be false
        return false;
    }
    evaluateCalculatedColumnQuery(calculatedColumn, rowNode) {
        try {
            if (this.adaptableApi.gridApi.isGroupRowNode(rowNode)) {
                return undefined;
            }
            // no validation here, this function has to be as performant as possible
            if (calculatedColumn?.Query?.ScalarExpression) {
                return this.adaptableApi.internalApi
                    .getQueryLanguageService()
                    .evaluateScalarExpression(calculatedColumn.Query.ScalarExpression, CalculatedColumnModuleId, rowNode);
            }
            if (calculatedColumn?.Query?.AggregatedScalarExpression) {
                const aggregatedScalarLiveValue = this.aggregatedScalarLiveValuesMap.get(calculatedColumn.Uuid);
                return aggregatedScalarLiveValue?.getAggregatedValueForRow(rowNode);
            }
        }
        catch (error) {
            this.adaptableApi.logError(`Invalid CalculatedColumn expression ${calculatedColumn?.Query?.ScalarExpression ??
                calculatedColumn?.Query?.AggregatedScalarExpression} :: ${error}`);
            return null;
        }
    }
    createAggregatedScalarLiveValue(calculatedColumn) {
        // if there is already an aggregated scalar, delete it (possible when editing)
        this.destroyAggregatedScalarLiveValue(calculatedColumn);
        if (calculatedColumn.Query?.AggregatedScalarExpression) {
            try {
                const aggregatedScalarLiveValue = new AggregatedScalarLiveValue({
                    aggregatedScalarExpression: calculatedColumn.Query?.AggregatedScalarExpression,
                }, CalculatedColumnModuleId, this.adaptableApi);
                this.aggregatedScalarLiveValuesMap.set(calculatedColumn.Uuid, aggregatedScalarLiveValue);
            }
            catch (e) {
                this.adaptableApi.logError(`Creating CalculatedColumn ('${calculatedColumn.Query?.AggregatedScalarExpression}') failed!`, e.message);
            }
        }
    }
    destroyAggregatedScalarLiveValue(calculatedColumn) {
        this.aggregatedScalarLiveValuesMap.delete(calculatedColumn.Uuid);
    }
}
