"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlertModule = void 0;
const tslib_1 = require("tslib");
const AlertRedux = tslib_1.__importStar(require("../Redux/ActionsReducers/AlertRedux"));
const InternalRedux = tslib_1.__importStar(require("../Redux/ActionsReducers/InternalRedux"));
const GeneralConstants_1 = require("../Utilities/Constants/GeneralConstants");
const ModuleConstants = tslib_1.__importStar(require("../Utilities/Constants/ModuleConstants"));
const ArrayExtensions_1 = require("../Utilities/Extensions/ArrayExtensions");
const getObjectTagsViewItems_1 = require("../Utilities/getObjectTagsViewItems");
const getRuleViewItems_1 = require("../Utilities/getRuleViewItems");
const getScopeViewItems_1 = require("../Utilities/getScopeViewItems");
const ActiveAlertsPanelItemLabel_1 = require("../View/Alert/ActiveAlertsPanelItemLabel");
const AlertEmptyView_1 = require("../View/Alert/AlertEmptyView");
const AlertStatusSubPanel_1 = require("../View/Alert/AlertStatusSubPanel");
const getAlertType_1 = require("../View/Alert/Utilities/getAlertType");
const AlertWizard_1 = require("../View/Alert/Wizard/AlertWizard");
const AdaptableModuleBase_1 = require("./AdaptableModuleBase");
const getAlertBehaviourViewItems_1 = require("./Utilities/Alert/getAlertBehaviourViewItems");
const getAlertPreviewViewItems_1 = require("./Utilities/Alert/getAlertPreviewViewItems");
const getAlertTypeViewItems_1 = require("./Utilities/Alert/getAlertTypeViewItems");
class AlertModule extends AdaptableModuleBase_1.AdaptableModuleBase {
    constructor(api) {
        super(ModuleConstants.AlertModuleId, ModuleConstants.AlertModuleFriendlyName, 'alert', 'AlertPopup', 'Get notified when things happen in Adaptable that you need to know about', api);
        this.isListeningToCellDataChanges = false;
    }
    onAdaptableReady() {
        this.checkListenToCellDataChanged();
    }
    shouldListenToDataChanges() {
        return ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(this.api.alertApi.getActiveAlertDefinitions());
    }
    checkListenToCellDataChanged() {
        if (!this.isListeningToCellDataChanges) {
            if (this.shouldListenToDataChanges()) {
                this.setupCellDataChangeListener();
                this.isListeningToCellDataChanges = true;
            }
        }
    }
    setupCellDataChangeListener() {
        this.api.internalApi
            .getDataService()
            .on('CellDataChanged', (cellDataChangedInfo) => {
            let shouldIgnoreChange = false;
            if (cellDataChangedInfo.trigger === 'undo') {
                shouldIgnoreChange = true;
            }
            if (cellDataChangedInfo.trigger === 'aggChange') {
                shouldIgnoreChange = !cellDataChangedInfo.column.isGeneratedPivotResultColumn;
            }
            if (shouldIgnoreChange) {
                // do NOT handle reverted or aggregated changes
                return;
            }
            if (this.api.optionsApi.getAlertOptions().dataChangeDetectionPolicy === 'formattedValue') {
                const { oldValue, newValue, rowNode } = cellDataChangedInfo;
                const columnId = cellDataChangedInfo.column.columnId;
                const oldFormattedValue = this.api.gridApi.getDisplayValueFromRawValue(rowNode, columnId, oldValue);
                const newFormattedValue = this.api.gridApi.getDisplayValueFromRawValue(rowNode, columnId, newValue);
                if (oldFormattedValue === newFormattedValue) {
                    // if the formattedValues are identical, then no alert is fired
                    return;
                }
            }
            this.handleCellDataChanged(cellDataChangedInfo);
        });
        this.api.internalApi
            .getDataService()
            .on('RowDataChanged', (rowDataChangedInfo) => {
            if (rowDataChangedInfo.rowTrigger === 'Update') {
                // changed row alerts should be handled by standard 'AnyChange' Predicate
                return;
            }
            this.handleRowDataChanged(rowDataChangedInfo);
        });
        this.api.internalApi
            .getAlertService()
            .onReactiveAlertTriggered((reactiveAlertInfo) => this.handleReactiveAlertTriggered(reactiveAlertInfo));
        this.api.alertApi.internalApi.setUpReactiveAlerts();
    }
    getModuleAdaptableObjects(config) {
        return this.api.alertApi.getAlertDefinitions(config);
    }
    getExplicitlyReferencedColumnIds(alertDefinition) {
        const queryExpression = this.api.expressionApi.getAdaptableQueryExpression(alertDefinition.Rule);
        if (queryExpression) {
            return this.api.expressionApi.getColumnsFromExpression(queryExpression);
        }
        else if (this.api.columnScopeApi.scopeHasColumns(alertDefinition.Scope)) {
            return this.api.columnScopeApi
                .getColumnsInScope(alertDefinition.Scope)
                .map((adaptableColumn) => adaptableColumn.columnId);
        }
        return [];
    }
    getReferencedNamedQueryNames(alertDefinition) {
        const queryExpression = this.api.expressionApi.getAdaptableQueryExpression(alertDefinition.Rule);
        if (!queryExpression) {
            return [];
        }
        return this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(queryExpression);
    }
    createContextMenuItems(menuContext) {
        const items = [];
        if (!menuContext.isRowGroupColumn && this.isModuleAvailable()) {
            if (menuContext.adaptableColumn && menuContext.rowNode) {
                let relevantAlert;
                // find alerts which highlight the current cell
                relevantAlert = this.api.alertApi.internalApi.getAdaptableAlertWithHighlightCell(menuContext.adaptableColumn.columnId, menuContext.rowNode);
                if (!relevantAlert) {
                    // find alerts which highlight the current row
                    relevantAlert = this.api.alertApi.internalApi.getAdaptableAlertWithHighlightRow(menuContext.rowNode);
                }
                if (relevantAlert) {
                    items.push(this.createMenuItemReduxAction('alert-clear', 'Clear Alert', this.moduleInfo.Glyph, InternalRedux.AdaptableAlertDelete(relevantAlert)));
                }
            }
        }
        return items;
    }
    handleCellDataChanged(cellDataChangedInfo) {
        const alertDefinitions = this.api.alertApi.internalApi.getAlertDefinitionsForCellDataChange(cellDataChangedInfo);
        if (ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(alertDefinitions)) {
            this.api.alertApi.internalApi.showAlertForDefinitions(cellDataChangedInfo, alertDefinitions);
        }
    }
    handleRowDataChanged(rowDataChangedInfo) {
        const alertDefinitions = this.getAlertDefinitionsForRowDataChange(rowDataChangedInfo);
        this.api.alertApi.internalApi.showAlertsForRowDataChanges(rowDataChangedInfo, alertDefinitions);
    }
    handleReactiveAlertTriggered(reactiveAlertInfo) {
        // TODO  - suppress Notification if alert is not relevant for layout
        if (reactiveAlertInfo.type === 'cellDataChangedAlert') {
            // the row node data is most probably stale because the reactive queries buffer the changed data
            // so we have to refresh it
            reactiveAlertInfo.cellChangeLogEntry.rowNode = this.api.gridApi.getRowNodeForPrimaryKey(reactiveAlertInfo.cellChangeLogEntry.primaryKeyValue);
            reactiveAlertInfo.cellChangeLogEntry.rowData =
                reactiveAlertInfo.cellChangeLogEntry.rowNode?.data;
            this.api.alertApi.internalApi.showAlertForDefinitions(reactiveAlertInfo.cellChangeLogEntry, [
                reactiveAlertInfo.alertDefinition,
            ]);
        }
        else {
            // reactiveAlertInfo.type === rowDataChangedAlert'
            this.api.alertApi.internalApi.showAlertForDefinitions(reactiveAlertInfo.gridChangeLogEntry, [
                reactiveAlertInfo.alertDefinition,
            ]);
        }
    }
    getAlertDefinitionsForRowDataChange(rowDataChangedInfo) {
        return this.api.alertApi.internalApi
            .getActiveNonReactiveAlertDefinitions()
            .filter((alertDefinition) => this.api.alertApi.internalApi.isAlertDefinitionForRowChangeEvent(alertDefinition))
            .filter((alertDefinition) => {
            if (rowDataChangedInfo.rowTrigger === 'Add') {
                return alertDefinition.Rule?.ObservableExpression.includes(GeneralConstants_1.OBSERVABLE_EXPRESSION_ROW_ADDED);
            }
            if (rowDataChangedInfo.rowTrigger === 'Delete') {
                return alertDefinition.Rule?.ObservableExpression.includes(GeneralConstants_1.OBSERVABLE_EXPRESSION_ROW_REMOVED);
            }
            return false;
        });
    }
    getTeamSharingAction() {
        return {
            ModuleEntities: this.api.alertApi.getAlertDefinitions(),
            AddAction: AlertRedux.AlertDefinitionAdd,
            EditAction: AlertRedux.AlertDefinitionEdit,
        };
    }
    toViewCompact(alert) {
        return {
            item: {
                name: alert.header,
                label: ActiveAlertsPanelItemLabel_1.ActiveAlertsPanelItemLabel,
                values: [alert.message],
            },
            abObject: alert,
        };
    }
    toView(alert) {
        const alertType = (0, getAlertType_1.getAlertType)(alert);
        return {
            items: [
                (0, getAlertTypeViewItems_1.getAlertTypeViewItems)(alert),
                alertType === 'DataChange' && {
                    ...(0, getScopeViewItems_1.getScopeViewItems)(alert.Scope, this.api),
                    label: 'Trigger',
                    name: 'Trigger',
                },
                { ...(0, getRuleViewItems_1.getRuleViewItems)(alert.Rule, this.api), label: 'Rule', name: 'Rule' },
                (0, getAlertBehaviourViewItems_1.getAlertBehaviourViewItems)(this.api),
                (0, getAlertPreviewViewItems_1.getAlertPreviewViewItems)(alert, this.api),
                (0, getObjectTagsViewItems_1.getObjectTagsViewItems)(alert, this.api),
            ].filter(Boolean),
            abObject: alert,
        };
    }
    toViewAll() {
        return this.getModuleAdaptableObjects({
            includeLayoutNotAssociatedObjects: this.showLayoutNotAssociatedObjects(),
        }).map((alert) => this.toView(alert));
    }
    getViewProperties() {
        return {
            getDeleteAction: AlertRedux.AlertDefinitionDelete,
            getEditAction: AlertRedux.AlertDefinitionEdit,
            getSuspendAction: AlertRedux.AlertDefinitionSuspend,
            getUnSuspendAction: AlertRedux.AlertDefinitionUnSuspend,
            getSuspendAllAction: AlertRedux.AlertDefinitionSuspendAll,
            getUnSuspendAllAction: AlertRedux.AlertDefinitionUnSuspendAll,
            getCompactDeleteAction: InternalRedux.AdaptableAlertDelete,
            getDeleteAllAction: () => {
                const alerts = this.api.internalApi.getState().Internal.AdaptableAlerts;
                return InternalRedux.AdaptableAlertDeleteAll(alerts);
            },
            emptyView: AlertEmptyView_1.AlertEmptyView,
            getEditWizard: () => AlertWizard_1.AlertWizard,
            getStatusBarPanelProps: () => {
                return {
                    popoverMinWidth: 360,
                    view: AlertStatusSubPanel_1.AlertStatusPanel,
                };
            },
        };
    }
    canBeAssociatedWithLayouts() {
        return true;
    }
}
exports.AlertModule = AlertModule;
