import { ApiBase } from './ApiBase';
import * as parser from '../../parser/src';
import { ExpressionInternalApi } from '../Internal/ExpressionInternalApi';
export class ExpressionApiImpl extends ApiBase {
    internalApi;
    constructor(_adaptable) {
        super(_adaptable);
        this.internalApi = new ExpressionInternalApi(_adaptable);
    }
    isValidBooleanExpression(query, module, validationErrorMessage) {
        const { isValid, errorMessage } = this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .validateBoolean(query, module, { force: true });
        if (!isValid && validationErrorMessage) {
            this.logWarn(`${validationErrorMessage} :: ${errorMessage}`);
        }
        return isValid;
    }
    isValidObservableExpression(expression, module, validationErrorMessage) {
        const { isValid, errorMessage } = this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .validateObservable(expression, module);
        if (!isValid && validationErrorMessage) {
            this.logWarn(`${validationErrorMessage} :: ${errorMessage}`);
        }
        return isValid;
    }
    isValidAggregatedBooleanExpression(expression, module, validationErrorMessage) {
        const { isValid, errorMessage } = this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .validateAggregatedBoolean(expression, module);
        if (!isValid && validationErrorMessage) {
            this.logWarn(`${validationErrorMessage} :: ${errorMessage}`);
        }
        return isValid;
    }
    isValidAggregatedScalarExpression(expression, module, validationErrorMessage) {
        const { isValid, errorMessage } = this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .validateAggregatedScalar(expression, module);
        if (!isValid && validationErrorMessage) {
            this.logWarn(`${validationErrorMessage} :: ${errorMessage}`);
        }
        return isValid;
    }
    getASTForExpression(query) {
        return parser.getAbstractSyntaxTree(query);
    }
    getColumnsFromExpression(expression) {
        try {
            const columnIds = this.getAdaptableApi()
                .internalApi.getQueryLanguageService()
                .getColumnsFromExpression(expression);
            columnIds.forEach((columnId) => {
                const calculatedColumn = this.getCalculatedColumnApi().getCalculatedColumnForColumnId(columnId);
                if (calculatedColumn) {
                    const transitiveColumnIds = this.getColumnsFromExpression(this.getAdaptableQueryExpression(calculatedColumn.Query));
                    columnIds.push(...transitiveColumnIds);
                }
            });
            return Array.from(new Set(columnIds));
        }
        catch (error) {
            // defensive programing, this should happen only if someone botched Initial Adaptable State
            this.logWarn(`QueryApi.getColumnsFromExpressionInvalid received an invalid expression: ${expression}
                  Error: ${error}`);
            return [];
        }
    }
    isColumnQueryable(abColumn) {
        let queryableColumnFn = this.getExpressionOptions().isColumnQueryable;
        if (queryableColumnFn) {
            const queryableColumnContext = {
                column: abColumn,
                ...this.getAdaptableInternalApi().buildBaseContext(),
            };
            return queryableColumnFn(queryableColumnContext);
        }
        return true;
    }
    getAdaptableQueryExpression(query) {
        return (query.BooleanExpression ??
            query.ScalarExpression ??
            query.ObservableExpression ??
            query.AggregatedBooleanExpression ??
            query.AggregatedScalarExpression);
    }
    getAdaptableQueryExpressionWithColumnFriendlyNames(query) {
        return this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .getExpressionWithColumnFriendlyNames(this.getAdaptableQueryExpression(query));
    }
    useCaseSensitivity() {
        return this.getExpressionOptions().caseSensitiveExpressions;
    }
}
