"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlertInternalApi = void 0;
const tslib_1 = require("tslib");
const ApiBase_1 = require("../Implementation/ApiBase");
const AdaptableQuery_1 = require("../../PredefinedConfig/Common/AdaptableQuery");
const AdaptableAlert_1 = require("../../PredefinedConfig/Common/AdaptableAlert");
const ArrayExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/ArrayExtensions"));
const ModuleConstants_1 = require("../../Utilities/Constants/ModuleConstants");
const IAlertService_1 = require("../../Utilities/Services/Interface/IAlertService");
const ObjectFactory_1 = tslib_1.__importDefault(require("../../Utilities/ObjectFactory"));
const Helper_1 = tslib_1.__importDefault(require("../../Utilities/Helpers/Helper"));
class AlertInternalApi extends ApiBase_1.ApiBase {
    getExpressionForAlertRule(alertRule) {
        var expression;
        expression = alertRule.BooleanExpression
            ? alertRule.BooleanExpression
            : alertRule.AggregatedBooleanExpression
                ? alertRule.AggregatedBooleanExpression
                : alertRule.ObservableExpression
                    ? alertRule.ObservableExpression
                    : undefined;
        return expression;
    }
    /**
     * Retrieves the Adaptable Form with the given name
     * @param name name of the Form
     */
    getAdaptableFormByName(name) {
        var _a;
        const alertForms = this.getAlertOptions().alertForms || [];
        return (_a = alertForms.find((f) => f.name === name)) === null || _a === void 0 ? void 0 : _a.form;
    }
    /**
     * Retrieves all Alert Definitions in Alert State which are NOT Reactive (BooleanQuery)
     * @returns alert definitions
     */
    getNonReactiveAlertDefinitions() {
        return this.getAlertApi()
            .getAlertDefinitions()
            .filter((alertDef) => !(0, AdaptableQuery_1.isReactiveQuery)(alertDef.Rule));
    }
    /**
     * Retrieves all active (non-suspended) Alert Definitions in Alert State which are NOT Reactive (BooleanQuery)
     * @returns alert definitions
     */
    getActiveNonReactiveAlertDefinitions() {
        return this.getNonReactiveAlertDefinitions().filter((alertDef) => !alertDef.IsSuspended);
    }
    /**
     *
     * Retrieves all Alert Definitions in Alert State which are reactive (ObservableQuery & AggregationQuery)
     * @returns alert definitions
     */
    getReactiveAlertDefinitions() {
        return this.getAlertApi()
            .getAlertDefinitions()
            .filter((alertDef) => (0, AdaptableQuery_1.isReactiveQuery)(alertDef.Rule));
    }
    /**
     *
     * Retrieves all active (non-suspended) Alert Definitions in Alert State which are reactive (ObservableQuery & AggregationQuery)
     * @returns alert definitions
     */
    getActiveReactiveAlertDefinitions() {
        return this.getReactiveAlertDefinitions().filter((alertDef) => !alertDef.IsSuspended);
    }
    /**
     * Retrieves all Alert Definitions which prevent a Cell Edit
     * @returns alert definitions
     */
    getAlertDefinitionsWithPreventEdit() {
        return this.getActiveNonReactiveAlertDefinitions().filter((a) => a.AlertProperties != null && a.AlertProperties.PreventEdit === true);
    }
    /**
     * Retrieves all Alert Definitions which allow a Cell Edit
     *  @returns alert definitions
     */
    getAlertDefinitionsWithAllowEdit() {
        return this.getActiveNonReactiveAlertDefinitions().filter((a) => a.AlertProperties == null || a.AlertProperties.PreventEdit !== true);
    }
    /**
     * Publishes an event when an Alert is triggered
     * @param alertToFire Alerts which has just triggered
     */
    publishAlertFiredEvent(alertToFire) {
        const alertFiredInfo = Object.assign({ alert: alertToFire }, this.getAdaptableInternalApi().buildBaseContext());
        this.getEventApi().emit('AlertFired', alertFiredInfo);
    }
    /**
     * Runs after a button in an Alert Form is clicked
     */
    executeAlertButton(button, context) {
        if (button.Action) {
            let actions = button.Action;
            if (typeof actions === 'function') {
                actions(context);
                return;
            }
            if (!Array.isArray(actions)) {
                actions = [actions];
            }
            actions.forEach((action) => {
                var _a;
                const buttonOnClick = (_a = this.getAlertOptions().actionHandlers) === null || _a === void 0 ? void 0 : _a.find((x) => x.name === action);
                buttonOnClick === null || buttonOnClick === void 0 ? void 0 : buttonOnClick.handler(button, context);
                this.executeAlertAction(action, {
                    alertDefinition: context.alert.alertDefinition,
                    cellDataChangedInfo: (0, AdaptableAlert_1.isAdaptableCellChangedAlert)(context.alert)
                        ? context.alert.cellDataChangedInfo
                        : null,
                    gridDataChangedInfo: (0, AdaptableAlert_1.isAdaptableRowChangedAlert)(context.alert)
                        ? context.alert.gridDataChangedInfo
                        : null,
                    formData: context.formData,
                });
            });
        }
    }
    /**
     * Runs after an Alert Action is invoked
     * @param actionName Action which has been invoked
     * @param details Info about the Alert and Form
     */
    executeAlertAction(actionName, details) {
        const { alertDefinition, cellDataChangedInfo: cellDataChangedInfo, gridDataChangedInfo, } = details;
        const getBackgroundColor = (alertDefinition) => {
            var _a;
            const highlightType = (_a = alertDefinition.MessageType) !== null && _a !== void 0 ? _a : 'Info';
            let backgroundColor = '';
            switch (highlightType) {
                case 'Error':
                    backgroundColor = 'var(--ab-color-error)';
                    break;
                case 'Info':
                    backgroundColor = 'var(--ab-color-info)';
                    break;
                case 'Success':
                    backgroundColor = 'var(--ab-color-success)';
                    break;
                case 'Warning':
                    backgroundColor = 'var(--ab-color-warn)';
            }
            return backgroundColor;
        };
        if (actionName === 'highlight-cell' && cellDataChangedInfo) {
            const backgroundColor = getBackgroundColor(alertDefinition);
            this.getGridApi().highlightCell({
                columnId: cellDataChangedInfo.column.columnId,
                primaryKeyValue: cellDataChangedInfo.primaryKeyValue,
                highlightStyle: {
                    BackColor: backgroundColor,
                },
                timeout: this.getAlertOptions().cellHighlightDuration,
            });
        }
        if (actionName === 'highlight-row' && cellDataChangedInfo) {
            const rowsHighlightInfo = {
                primaryKeyValues: [cellDataChangedInfo.primaryKeyValue],
                highlightStyle: {
                    BackColor: getBackgroundColor(alertDefinition),
                },
                timeout: this.getAlertOptions().rowHighlightDuration,
            };
            this.getGridApi().highlightRows(rowsHighlightInfo);
        }
        if (actionName === 'highlight-row' &&
            gridDataChangedInfo &&
            // no sense to highlight a deleted(non-existing) row
            (gridDataChangedInfo === null || gridDataChangedInfo === void 0 ? void 0 : gridDataChangedInfo.rowTrigger) !== 'Delete') {
            const primaryKeyValues = this.getGridApi().getPrimaryKeyValuesForRowNodes(gridDataChangedInfo.rowNodes);
            const rowsHighlightInfo = {
                primaryKeyValues,
                highlightStyle: {
                    BackColor: getBackgroundColor(alertDefinition),
                },
                timeout: this.getAlertOptions().rowHighlightDuration,
            };
            this.getGridApi().highlightRows(rowsHighlightInfo);
        }
        if (actionName === 'jump-to-cell' && cellDataChangedInfo) {
            this.getGridApi().jumpToCell(cellDataChangedInfo.primaryKeyValue, cellDataChangedInfo.column.columnId);
        }
        if (actionName === 'jump-to-row' &&
            // either a cell change
            (cellDataChangedInfo ||
                // or a grid change, but NOT row deletion
                (gridDataChangedInfo &&
                    // no sense to jump to a deleted(non-existing) row
                    (gridDataChangedInfo === null || gridDataChangedInfo === void 0 ? void 0 : gridDataChangedInfo.rowTrigger) !== 'Delete'))) {
            const [firstRowNode] = cellDataChangedInfo
                ? [cellDataChangedInfo.rowNode]
                : gridDataChangedInfo.rowNodes;
            const targetRowNodePrimaryKeyValue = this.getGridApi().getPrimaryKeyValueForRowNode(firstRowNode);
            if (targetRowNodePrimaryKeyValue) {
                this.getGridApi().jumpToRow(targetRowNodePrimaryKeyValue);
            }
        }
        if (actionName === 'jump-to-column' && cellDataChangedInfo) {
            this.getGridApi().jumpToColumn(cellDataChangedInfo.column.columnId);
        }
        if (actionName === 'suspend') {
            this.getAlertApi().suspendAlertDefinition(alertDefinition);
        }
        if (actionName === 'undo' && cellDataChangedInfo) {
            this.getGridApi().undoCellEdit(cellDataChangedInfo);
        }
    }
    /**
     * Retrieves all Predicate Defs that match given Scope
     * @param scope the Scope to check
     */
    getAlertPredicateDefsForScope(scope) {
        return this.getPredicateApi()
            .internalApi.getAlertPredicateDefs(scope)
            .filter((predicateDef) => this.getColumnScopeApi().isScopeInScope(scope, predicateDef.columnScope));
    }
    /**
     * Returns a description of an Alert Definition
     * @param alertDefinition Alert Definition to use
     */
    getAlertDescriptionForDataChange(alertDefinition, cellDataChangedInfo) {
        let customMessage = this.getCustomAlertDescription(alertDefinition, { cellDataChangedInfo });
        const anotationContext = cellDataChangedInfo
            ? {
                column: cellDataChangedInfo.column,
                rowNode: cellDataChangedInfo.rowNode,
                oldValue: cellDataChangedInfo.oldValue,
                newValue: cellDataChangedInfo.newValue,
                primaryKeyValue: cellDataChangedInfo.primaryKeyValue,
                timestamp: cellDataChangedInfo.changedAt,
                trigger: cellDataChangedInfo.trigger,
            }
            : {};
        if (customMessage) {
            customMessage = cellDataChangedInfo
                ? this.annotateAlertText(customMessage, anotationContext)
                : customMessage;
            return customMessage;
        }
        if (alertDefinition.MessageText != null) {
            let alertText = alertDefinition.MessageText;
            try {
                alertText = cellDataChangedInfo
                    ? this.annotateAlertText(alertText, anotationContext)
                    : alertText;
                return alertText;
            }
            catch (e) {
                this.logError('Error in getAlertMessageHeader', e);
            }
        }
        let scopeDescription = this.getColumnScopeApi().getScopeDescription(alertDefinition.Scope);
        let ruleDescription = this.getAlertRuleDescription(alertDefinition);
        return scopeDescription + ' - ' + ruleDescription;
    }
    /**
     * Returns a description title of an Alert Definition
     * @param alertDefinition Alert Definition to use
     */
    getAlertMessageHeaderForDataChange(alertDefinition, cellDataChangedInfo) {
        var _a, _b;
        const anotationContext = cellDataChangedInfo
            ? {
                column: cellDataChangedInfo.column,
                rowNode: cellDataChangedInfo.rowNode,
                oldValue: cellDataChangedInfo.oldValue,
                newValue: cellDataChangedInfo.newValue,
                primaryKeyValue: cellDataChangedInfo.primaryKeyValue,
                timestamp: cellDataChangedInfo.changedAt,
                trigger: cellDataChangedInfo.trigger,
            }
            : {};
        let message = (_a = this.getCustomAlertMessageHeader(alertDefinition, {
            cellDataChangedInfo,
        })) !== null && _a !== void 0 ? _a : (_b = cellDataChangedInfo === null || cellDataChangedInfo === void 0 ? void 0 : cellDataChangedInfo.column) === null || _b === void 0 ? void 0 : _b.friendlyName;
        try {
            message = cellDataChangedInfo ? this.annotateAlertText(message, anotationContext) : message;
        }
        catch (e) {
            this.logError('Error in getAlertMessageHeader', e);
        }
        return message;
    }
    getAlertMessageForGridDataChange(alertDefinition, gridDataChangedInfo) {
        const rowAdded = gridDataChangedInfo.rowTrigger === 'Add';
        const numberOfChangedRows = gridDataChangedInfo.rowNodes.length;
        const actionName = rowAdded ? 'Added' : 'Removed';
        const defaultMessage = numberOfChangedRows > 1
            ? `${numberOfChangedRows} rows were ${actionName.toLowerCase()}`
            : `${numberOfChangedRows} row was ${actionName.toLowerCase()}`;
        const customMessage = this.getCustomAlertDescription(alertDefinition, {
            gridDataChangedInfo,
        });
        let alertMessage = alertDefinition.MessageText
            ? alertDefinition.MessageText
            : customMessage !== null && customMessage !== void 0 ? customMessage : defaultMessage;
        try {
            alertMessage = this.annotateAlertText(alertMessage, {
                numberOfRows: numberOfChangedRows,
                timestamp: gridDataChangedInfo.changedAt,
                trigger: gridDataChangedInfo.rowTrigger,
            });
        }
        catch (e) {
            this.logError('Error in getAlertMessageForGridDataChange', e);
        }
        return alertMessage;
    }
    getAlertHeaderForGridDataChange(alertDefinition, gridDataChangedInfo) {
        const rowAdded = gridDataChangedInfo.rowTrigger === 'Add';
        const numberOfChangedRows = gridDataChangedInfo.rowNodes.length;
        const actionName = rowAdded ? 'Added' : 'Removed';
        const customHeader = this.getCustomAlertMessageHeader(alertDefinition, {
            gridDataChangedInfo,
        });
        const alertHeader = numberOfChangedRows > 1 ? `${actionName} Rows` : `${actionName} Row `;
        let header = customHeader !== null && customHeader !== void 0 ? customHeader : alertHeader;
        try {
            header = this.annotateAlertText(header, {
                numberOfRows: numberOfChangedRows,
                timestamp: gridDataChangedInfo.changedAt,
                trigger: gridDataChangedInfo.rowTrigger,
            });
        }
        catch (e) {
            this.logError('Error in getAlertHeaderForGridDataChange', e);
        }
        return header;
    }
    /**
     * Returns custom description for alert using the 'alertMessageText' property
     *
     * @param alertDefinition Alert Definition to use
     * @param dataChangedInfo data change info, it can be eighter grid or cell data chantged info
     */
    getCustomAlertDescription(alertDefinition, dataChangedInfo) {
        var _a;
        const alertMessageFunction = (_a = this.getAlertOptions()) === null || _a === void 0 ? void 0 : _a.alertMessageText;
        if (alertMessageFunction) {
            const alertMessageContext = {
                alertDefinition: alertDefinition,
                cellDataChangedInfo: dataChangedInfo.cellDataChangedInfo,
                gridDataChangedInfo: dataChangedInfo.gridDataChangedInfo,
            };
            const returnText = alertMessageFunction(alertMessageContext);
            if (returnText) {
                return returnText;
            }
        }
        return null;
    }
    /**
     * Returns custom title defined by 'alertMessageHeader' property
     * @param alertDefinition Alert Definition to use
     * @param dataChangedInfo Data change info, it can be eighter grid or cell data chantged info
     */
    getCustomAlertMessageHeader(alertDefinition, dataChangedInfo) {
        var _a;
        const alertMessageFunction = (_a = this.getAlertOptions()) === null || _a === void 0 ? void 0 : _a.alertMessageHeader;
        if (alertMessageFunction) {
            const returnText = alertMessageFunction({
                alertDefinition,
                cellDataChangedInfo: dataChangedInfo === null || dataChangedInfo === void 0 ? void 0 : dataChangedInfo.cellDataChangedInfo,
                gridDataChangedInfo: dataChangedInfo === null || dataChangedInfo === void 0 ? void 0 : dataChangedInfo.gridDataChangedInfo,
            });
            if (returnText) {
                return returnText;
            }
        }
        if (alertDefinition.MessageHeader) {
            return alertDefinition.MessageHeader;
        }
        return null;
    }
    /**
     * Returns a description of an Alert Definition's Rule
     * @param alertDefinition Alert Definition to use
     */
    getAlertRuleDescription(alertDefinition) {
        var _a, _b, _c, _d;
        let ruleDescription = ((_b = (_a = alertDefinition.Rule) === null || _a === void 0 ? void 0 : _a.Predicates) === null || _b === void 0 ? void 0 : _b.length)
            ? (_d = (_c = alertDefinition.Rule) === null || _c === void 0 ? void 0 : _c.Predicates) === null || _d === void 0 ? void 0 : _d.map((predicate) => this.getPredicateApi().predicateToString(predicate)).join(' AND ')
            : this.getAdaptableInternalApi().getAdaptableQueryExpressionText(alertDefinition.Rule);
        return ruleDescription;
    }
    /**
     * Was Adaptable Alert fired due to a Cell Change
     * @param alert AdaptableAlert to check
     */
    isCellChangedAdaptableAlert(alert) {
        return alert.alertType === 'cellChanged';
    }
    /**
     * Was Adaptable Alert fired due to a Row Change
     * @param alert AdaptableAlert to check
     */
    isRowChangedAdaptableAlert(alert) {
        return alert.alertType === 'rowChanged';
    }
    /**
     * Is Adaptable Alert a Generic one
     * @param alert AdaptableAlert to check
     */
    isGenericAdaptableAlert(alert) {
        return alert.alertType === 'generic';
    }
    /**
     * Returns for the Alert Type for an Adaptable Alert
     * @param alert AdaptableAlert to check
     */
    getAlertTypeForAdaptableAlert(alert) {
        return alert.alertType;
    }
    getAdaptableFormFromAlertForm(alertForm, context, defaultMessageType) {
        var _a, _b;
        let adaptableAlertForm;
        let isActionForm = false;
        if (typeof alertForm === 'string') {
            const alertForms = this.getAlertOptions().alertForms || [];
            adaptableAlertForm = (_a = alertForms.find((f) => f.name === alertForm)) === null || _a === void 0 ? void 0 : _a.form;
        }
        else {
            adaptableAlertForm = Object.assign(Object.assign({}, alertForm), { buttons: (alertForm.Buttons || []).map((alertButton) => {
                    return Object.assign(Object.assign({}, alertButton), { onClick: () => {
                            this.executeAlertButton(alertButton, context);
                        } });
                }) });
            isActionForm = true;
        }
        if (!adaptableAlertForm) {
            return;
        }
        if (adaptableAlertForm && adaptableAlertForm.buttons) {
            // dont mutate the form, but clone it
            adaptableAlertForm = Object.assign({}, adaptableAlertForm);
            adaptableAlertForm.buttons = (_b = adaptableAlertForm.buttons) === null || _b === void 0 ? void 0 : _b.map((button) => {
                let buttonStyle = isActionForm
                    ? button.ButtonStyle
                    : this.getAdaptableInternalApi().getStyleForButton(button, context);
                if (defaultMessageType && !(buttonStyle === null || buttonStyle === void 0 ? void 0 : buttonStyle.tone)) {
                    // force the button tone to be the alert tone, if the tone is missing from button style (or button style non-existent)
                    buttonStyle = Object.assign(Object.assign({}, buttonStyle), { tone: defaultMessageType.toLowerCase() });
                }
                let label = isActionForm
                    ? button.Label
                    : this.getAdaptableInternalApi().getLabelForButton(button, context);
                return Object.assign(Object.assign({}, button), { buttonStyle,
                    label });
            });
        }
        return adaptableAlertForm;
    }
    getAdaptableAlerts() {
        var _a;
        return (_a = this.getAdaptableState().System.AdaptableAlerts) !== null && _a !== void 0 ? _a : [];
    }
    getAdaptableCellChangedAlerts() {
        return this.getAdaptableAlerts().filter(AdaptableAlert_1.isAdaptableCellChangedAlert);
    }
    getAdaptableRowChangedAlerts() {
        return this.getAdaptableAlerts().filter(AdaptableAlert_1.isAdaptableRowChangedAlert);
    }
    getAdaptableAlertWithHighlightCell(columnId, rowNode) {
        // only alerts triggered by cell changes are relevant for HighlightCell actions
        return this.getAdaptableCellChangedAlerts().find((alert) => {
            var _a, _b, _c, _d;
            return ((_a = alert.alertDefinition.AlertProperties) === null || _a === void 0 ? void 0 : _a.HighlightCell) &&
                ((_c = (_b = alert.cellDataChangedInfo) === null || _b === void 0 ? void 0 : _b.column) === null || _c === void 0 ? void 0 : _c.columnId) === columnId &&
                ((_d = alert.cellDataChangedInfo) === null || _d === void 0 ? void 0 : _d.rowNode) === rowNode;
        });
    }
    getAdaptableAlertWithHighlightRow(rowNode) {
        let alertWithRowHighlight;
        alertWithRowHighlight = this.getAdaptableRowChangedAlerts().find((alert) => {
            var _a, _b;
            if ((_a = alert.alertDefinition.AlertProperties) === null || _a === void 0 ? void 0 : _a.HighlightRow) {
                if ((_b = alert.gridDataChangedInfo) === null || _b === void 0 ? void 0 : _b.rowNodes.map((rowNode) => rowNode.id).includes(rowNode.id)) {
                    return alert;
                }
            }
        });
        if (alertWithRowHighlight) {
            return alertWithRowHighlight;
        }
        alertWithRowHighlight = this.getAdaptableCellChangedAlerts().find((alert) => {
            var _a, _b;
            if ((_a = alert.alertDefinition.AlertProperties) === null || _a === void 0 ? void 0 : _a.HighlightRow) {
                if (((_b = alert.cellDataChangedInfo) === null || _b === void 0 ? void 0 : _b.rowNode.id) == rowNode.id) {
                    return alert;
                }
            }
        });
        return alertWithRowHighlight;
    }
    isAlertDefinitionForAddedRowChangeEvent(alertDefinition) {
        var _a, _b, _c;
        const addedRowPredicate = 'AddedRow';
        return (_c = (_b = (_a = alertDefinition === null || alertDefinition === void 0 ? void 0 : alertDefinition.Rule) === null || _a === void 0 ? void 0 : _a.Predicates) === null || _b === void 0 ? void 0 : _b.some) === null || _c === void 0 ? void 0 : _c.call(_b, (predicate) => predicate.PredicateId === addedRowPredicate);
    }
    isAlertDefinitionForRemovedRowChangeEvent(alertDefinition) {
        var _a, _b, _c;
        const removedRowPredicate = 'RemovedRow';
        return (_c = (_b = (_a = alertDefinition === null || alertDefinition === void 0 ? void 0 : alertDefinition.Rule) === null || _a === void 0 ? void 0 : _a.Predicates) === null || _b === void 0 ? void 0 : _b.some) === null || _c === void 0 ? void 0 : _c.call(_b, (predicate) => predicate.PredicateId === removedRowPredicate);
    }
    getAlertDefinitionsForCellDataChange(dataChangedEvent) {
        const allActiveNonReactiveDefinitions = this.getActiveNonReactiveAlertDefinitions();
        let relatedAlertDefinitions = allActiveNonReactiveDefinitions
            .filter((v) => this.getColumnScopeApi().isColumnInScope(dataChangedEvent.column, v.Scope))
            .filter((alertDefinition) => !(0, AdaptableQuery_1.isReactiveQuery)(alertDefinition.Rule));
        let triggeredAlerts = [];
        if (ArrayExtensions_1.default.IsNotNullOrEmpty(relatedAlertDefinitions)) {
            relatedAlertDefinitions.forEach((alertDefinition) => {
                if (alertDefinition.Rule.BooleanExpression) {
                    let expression = alertDefinition.Rule.BooleanExpression;
                    let rowNode = dataChangedEvent.rowNode;
                    if (!rowNode) {
                        rowNode = this.getGridApi().getRowNodeForPrimaryKey(dataChangedEvent.primaryKeyValue);
                    }
                    const isValidExpression = this.getAdaptableApi().expressionApi.isValidBooleanExpression(expression, 'Alert', `Invalid Alert boolean expression '${expression}'`);
                    const isSatisfiedExpression = isValidExpression &&
                        this.getAdaptableApi()
                            .internalApi.getQueryLanguageService()
                            .evaluateBooleanExpression(expression, 'Alert', rowNode);
                    if (isSatisfiedExpression) {
                        triggeredAlerts.push(alertDefinition);
                    }
                }
                else if (alertDefinition.Rule.AggregatedBooleanExpression) {
                    const isValidExpression = this.getAdaptableApi().expressionApi.isValidAggregatedBooleanExpression(alertDefinition.Rule.AggregatedBooleanExpression, 'Alert', `Invalid Alert boolean expression '${alertDefinition.Rule.AggregatedBooleanExpression}'`);
                    const isSatisfiedExpression = isValidExpression &&
                        this.isAggregationAlertTriggered(alertDefinition, dataChangedEvent);
                    if (isSatisfiedExpression) {
                        triggeredAlerts.push(alertDefinition);
                    }
                }
                else {
                    if (!this.isAlertDefinitionForRowChangeEvent(alertDefinition) &&
                        this.isAlertPredicateTriggered(alertDefinition, dataChangedEvent)) {
                        triggeredAlerts.push(alertDefinition);
                    }
                }
            });
            ``;
        }
        return triggeredAlerts;
    }
    isAggregationAlertTriggered(alertDefinition, dataChangedEvent) {
        const changedColumn = dataChangedEvent.column.columnId;
        const aggregationColumns = this.getAdaptableApi().expressionApi.getColumnsFromExpression(alertDefinition.Rule.AggregatedBooleanExpression);
        if (!aggregationColumns.includes(changedColumn)) {
            return false;
        }
        const aggregatedBooleanValue = this.getAdaptableApi()
            .internalApi.getQueryLanguageService()
            .computeAggregatedBooleanValue(alertDefinition.Rule.AggregatedBooleanExpression, ModuleConstants_1.AlertModuleId);
        return aggregatedBooleanValue;
    }
    isAlertPredicateTriggered(alert, dataChangedEvent, defaultNoPredicateReturn = false) {
        var _a;
        const predicateDefHandlerContext = Object.assign({ value: dataChangedEvent.newValue, oldValue: dataChangedEvent.oldValue, 
            // TODO send real display value
            displayValue: null, node: dataChangedEvent.rowNode, column: dataChangedEvent.column }, this.getAdaptableInternalApi().buildBaseContext());
        return this.getPredicateApi().handleColumnPredicates((_a = alert.Rule) === null || _a === void 0 ? void 0 : _a.Predicates, predicateDefHandlerContext, defaultNoPredicateReturn);
    }
    isAlertDefinitionForRowChangeEvent(alertDefinition) {
        return (this.isAlertDefinitionForAddedRowChangeEvent(alertDefinition) ||
            this.isAlertDefinitionForRemovedRowChangeEvent(alertDefinition));
    }
    showAlertForDefinitions(dataChangedInfo, alertDefinitions = []) {
        if ((0, IAlertService_1.isCellDataChangedInfo)(dataChangedInfo)) {
            alertDefinitions.forEach((alertDefinition) => {
                if (this.shouldFireAlertOnClient(alertDefinition)) {
                    const alert = ObjectFactory_1.default.CreateCellChangedAlert(this.getAlertMessageHeaderForDataChange(alertDefinition, dataChangedInfo), this.getAlertDescriptionForDataChange(alertDefinition, dataChangedInfo), alertDefinition, dataChangedInfo);
                    this.getAdaptableApi().alertApi.showAdaptableAlert(alert);
                }
            });
        }
        else {
            this.showAlertsForGridDataChanges(dataChangedInfo, alertDefinitions);
        }
    }
    showAlertsForGridDataChanges(gridDataChangedInfo, alertDefinitions) {
        alertDefinitions === null || alertDefinitions === void 0 ? void 0 : alertDefinitions.forEach((alertDefinition) => {
            if (this.shouldFireAlertOnClient(alertDefinition)) {
                const alert = ObjectFactory_1.default.CreateRowChangedAlert(this.getAlertHeaderForGridDataChange(alertDefinition, gridDataChangedInfo), this.getAlertMessageForGridDataChange(alertDefinition, gridDataChangedInfo), alertDefinition, gridDataChangedInfo);
                this.getAlertApi().showAdaptableAlert(alert);
            }
        });
    }
    shouldFireAlertOnClient(alertDefinition) {
        const rule = alertDefinition.Rule;
        if (rule) {
            if (rule.Predicates) {
                return this.getAdaptableApi().expressionApi.internalApi.evaluatePredicatesInAdaptableQL('Alert', alertDefinition, alertDefinition.Rule.Predicates);
            }
            else {
                var expression = this.getExpressionForAlertRule(rule);
                return this.getAdaptableApi().expressionApi.internalApi.evaluateExpressionInAdaptableQL('Alert', alertDefinition, expression);
            }
        }
        return true;
    }
    getDefaultAlertNotificationForm() {
        // we still need the default Notification Form  for historical reasons
        // (i.e. to be able to display the AlertForm with the default buttons when the user has not defined any buttons)
        return {
            fields: [],
            Buttons: [this.getDefaultButton()],
        };
    }
    getDefaultButton() {
        return {
            Label: 'OK',
            ButtonStyle: {
                variant: 'raised',
            },
        };
    }
    /**
     * Supported tokens:
     * - column-that-changed-name -> [column]
     * - rowData.newValue -> [rowData.newValue]
     * - rowData.oldValue -> [rowData.oldValue]
     * - primaryKey -> [primaryKeyValue]
     * - timestamp -> [timestamp]
     * - trigger -> [trigger]
     */
    annotateAlertText(text, context) {
        var _a, _b, _c;
        if (!text) {
            return text;
        }
        if (!context) {
            return text;
        }
        if (context === null || context === void 0 ? void 0 : context.newValue) {
            text = Helper_1.default.replaceAll(text, '[newValue]', context.newValue);
        }
        if (context === null || context === void 0 ? void 0 : context.oldValue) {
            text = Helper_1.default.replaceAll(text, '[oldValue]', context.oldValue);
        }
        if (context === null || context === void 0 ? void 0 : context.primaryKeyValue) {
            text = Helper_1.default.replaceAll(text, '[primaryKeyValue]', context.primaryKeyValue);
        }
        if (context === null || context === void 0 ? void 0 : context.timestamp) {
            text = Helper_1.default.replaceAll(text, '[timestamp]', context.timestamp + '');
        }
        if (context === null || context === void 0 ? void 0 : context.numberOfRows) {
            text = Helper_1.default.replaceAll(text, '[numberOfRows]', context.numberOfRows + '');
        }
        if (context === null || context === void 0 ? void 0 : context.trigger) {
            const dataChangeTriggerMap = {
                edit: 'Edit',
                tick: 'Tick',
                undo: 'Undo',
                aggChange: 'AggChange',
            };
            const rowChangeTriggerMap = {
                Add: 'Added',
                Edit: 'Edited',
                Delete: 'Deleted',
                Load: 'Loaded',
            };
            const mappedTrigger = 
            // @ts-ignore
            (_a = (dataChangeTriggerMap[context.trigger] || rowChangeTriggerMap[context.trigger])) !== null && _a !== void 0 ? _a : context.trigger;
            text = Helper_1.default.replaceAll(text, '[trigger]', mappedTrigger);
        }
        if (context === null || context === void 0 ? void 0 : context.column) {
            text = Helper_1.default.replaceAll(text, '[column]', this.getColumnApi().getFriendlyNameForColumnId(context.column.columnId));
        }
        if (context === null || context === void 0 ? void 0 : context.rowNode) {
            const columns = Helper_1.default.extractColsFromText(text);
            for (const column of columns) {
                if (this.getColumnApi().getColumnWithColumnId(column)) {
                    text = Helper_1.default.replaceAll(text, `[rowData.${column}]`, this.getGridApi().getRawValueFromRowNode(context.rowNode, column));
                }
            }
        }
        if (text.indexOf('[context') !== -1) {
            const agGridContext = (_c = (_b = this.getAdaptableInternalApi()
                .getAgGridAdapter()).getGridOption) === null || _c === void 0 ? void 0 : _c.call(_b, 'context');
            const agGridContextKeys = Helper_1.default.extractContextKeysFromText(text);
            for (const key of agGridContextKeys) {
                if (agGridContext[key]) {
                    text = Helper_1.default.replaceAll(text, `[context.${key}]`, agGridContext[key]);
                }
            }
        }
        return text;
    }
}
exports.AlertInternalApi = AlertInternalApi;
