"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlashingCellModule = void 0;
const tslib_1 = require("tslib");
const FlashingCellRedux = tslib_1.__importStar(require("../Redux/ActionsReducers/FlashingCellRedux"));
const ModuleConstants = tslib_1.__importStar(require("../Utilities/Constants/ModuleConstants"));
const ArrayExtensions_1 = require("../Utilities/Extensions/ArrayExtensions");
const AdaptableModuleBase_1 = require("./AdaptableModuleBase");
const AdaptableQuery_1 = require("../PredefinedConfig/Common/AdaptableQuery");
const getScopeViewItems_1 = require("./Utilities/getScopeViewItems");
const getRuleViewItems_1 = require("./Utilities/getRuleViewItems");
const getFlashingCellDurationViewItems_1 = require("./Utilities/FlashingCell/getFlashingCellDurationViewItems");
const FlashingCellWizard_1 = require("../View/FlashingCell/Wizard/FlashingCellWizard");
const getObjectTagsViewItems_1 = require("./Utilities/getObjectTagsViewItems");
const getFlashingTargetViewItems_1 = require("./Utilities/FlashingCell/getFlashingTargetViewItems");
const getFlashingCellStyleViewItems_1 = require("./Utilities/FlashingCell/getFlashingCellStyleViewItems");
class FlashingCellModule extends AdaptableModuleBase_1.AdaptableModuleBase {
    constructor(api) {
        super(ModuleConstants.FlashingCellModuleId, ModuleConstants.FlashingCellFriendlyName, 'lightning', 'FlashingAlert', 'Flash cells when they change', api);
    }
    onAdaptableReady() {
        this.api.internalApi
            .getDataService()
            .on('CellDataChanged', (cellDataChangedInfo) => {
            if (cellDataChangedInfo.trigger === 'undo') {
                // do NOT handle reverted changes
                return;
            }
            // TODO: think about flashing row value only
            // - flash for the underlying small data changes, but the visual does not
            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);
        });
    }
    getModuleAdaptableObjects(config) {
        return this.api.flashingCellApi.getFlashingCellDefinitions(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
                .getColumnsForScope(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);
    }
    createColumnMenuItems(column) {
        if (column && this.isModuleEditable()) {
            if (!this.api.columnApi.isCalculatedColumn(column.columnId)) {
                const flashingCellDefinitions = this.api.flashingCellApi.getFlashingCellDefinitions();
                const flashingCellForCurrentColumn = flashingCellDefinitions.find((flashingCellDefinition) => {
                    return this.api.columnScopeApi.isColumnInScope(column, flashingCellDefinition.Scope);
                });
                if (flashingCellForCurrentColumn) {
                    return [
                        this.createMenuItemReduxAction('flashing-cell-delete', 'Delete Flashing Cell', this.moduleInfo.Glyph, FlashingCellRedux.FlashingCellDefinitionDelete(flashingCellForCurrentColumn)),
                    ];
                }
                return [
                    this.createMenuItemReduxAction('flashing-cell-add', 'Add Flashing Cell', this.moduleInfo.Glyph, FlashingCellRedux.FlashingCellDefinitionAdd({
                        Scope: {
                            ColumnIds: [column.columnId],
                        },
                        Rule: {
                            Predicates: [{ PredicateId: 'AnyChange' }],
                        },
                    })),
                ];
            }
        }
    }
    createContextMenuItems(menuContext) {
        const items = [];
        if (!menuContext.isRowGroupColumn && this.isModuleAvailable()) {
            if (menuContext.adaptableColumn && menuContext.rowNode) {
                const flashingCellForRow = this.api.flashingCellApi.internalApi.getAdaptableFlashingCellFor(menuContext.primaryKeyValue);
                const flashingCellForCell = this.api.flashingCellApi.internalApi.getAdaptableFlashingCellFor(menuContext.primaryKeyValue, menuContext.adaptableColumn.columnId);
                if (flashingCellForRow) {
                    if (flashingCellForRow.flashTarget === 'row' ||
                        (Array.isArray(flashingCellForRow === null || flashingCellForRow === void 0 ? void 0 : flashingCellForRow.flashTarget) &&
                            flashingCellForRow.flashTarget.includes('row'))) {
                        items.push(this.createMenuItemClickFunction('flashing-row-clear', 'Clear Flashing Row', this.moduleInfo.Glyph, () => this.api.internalApi
                            .getFlashingCellService()
                            .clearGridCellFlash(flashingCellForRow)));
                    }
                }
                else if (flashingCellForCell && flashingCellForCell.flashTarget === 'cell') {
                    items.push(this.createMenuItemClickFunction('flashing-cell-clear', 'Clear Flashing Cell', this.moduleInfo.Glyph, () => this.api.internalApi
                        .getFlashingCellService()
                        .clearGridCellFlash(flashingCellForCell)));
                }
            }
        }
        return items;
    }
    handleCellDataChanged(cellDataChangedInfo) {
        const flashingCellDefinitions = this.getFlashingCellDefinitionsForDataChange(cellDataChangedInfo);
        if (ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(flashingCellDefinitions)) {
            this.showFlashingCellsForDefinitions(cellDataChangedInfo, flashingCellDefinitions);
        }
    }
    showFlashingCellsForDefinitions(cellDataChangedInfo, flashingCellDefinitions = []) {
        const allColumnIds = this.api.columnApi.getColumns().map((c) => c.columnId);
        const columnDataType = cellDataChangedInfo.column.dataType;
        const numeric = columnDataType === 'Number';
        const isComparableType = numeric || columnDataType === 'Date';
        let up = false;
        let down = false;
        let direction = 'neutral';
        if (isComparableType) {
            const newValue = numeric
                ? Number(cellDataChangedInfo.newValue)
                : cellDataChangedInfo.newValue;
            const oldValue = numeric
                ? Number(cellDataChangedInfo.oldValue)
                : cellDataChangedInfo.oldValue;
            up = newValue > oldValue;
            down = newValue < oldValue;
            direction = up ? 'up' : down ? 'down' : 'neutral';
        }
        flashingCellDefinitions.forEach((flashingCellDefinition) => {
            var _a;
            let flashTarget = this.api.flashingCellApi.getFlashingCellFlashTarget(flashingCellDefinition);
            const flashColumnIds = { [cellDataChangedInfo.column.columnId]: true };
            /**
             * When flashing a row, all columns in that row are marked to flash.
             */
            if (flashTarget === 'row' || ((_a = flashTarget === null || flashTarget === void 0 ? void 0 : flashTarget.includes) === null || _a === void 0 ? void 0 : _a.call(flashTarget, 'row'))) {
                allColumnIds.forEach((colId) => {
                    flashColumnIds[colId] = true;
                });
            }
            const rowPrimaryKey = cellDataChangedInfo.primaryKeyValue;
            this.api.flashingCellApi.showFlashingCell({
                rowPrimaryKey,
                flashingCellDefinition: flashingCellDefinition,
                cellDataChangedInfo: cellDataChangedInfo,
                direction,
                flashTarget,
                flashColumnIds,
            });
        });
    }
    isFlashingTargetOnlyAggChange(flashingCellDefinition) {
        if (flashingCellDefinition.FlashTarget === 'aggFuncCell') {
            return true;
        }
        return (Array.isArray(flashingCellDefinition.FlashTarget) &&
            flashingCellDefinition.FlashTarget.length === 1 &&
            flashingCellDefinition.FlashTarget.includes('aggFuncCell'));
    }
    getFlashingCellDefinitionsForDataChange(dataChangedEvent) {
        const definitions = this.api.flashingCellApi.getActiveFlashingCellDefinitions();
        const defaultNoPredicateReturn = false;
        let relatedFlashingCellsDefinitions = definitions
            .filter((v) => this.api.columnScopeApi.isColumnInScope(dataChangedEvent.column, v.Scope))
            .filter((flashingCellDefinition) => !(0, AdaptableQuery_1.isReactiveQuery)(flashingCellDefinition.Rule));
        let triggeredFlashingCells = [];
        if (ArrayExtensions_1.ArrayExtensions.IsNotNullOrEmpty(relatedFlashingCellsDefinitions)) {
            relatedFlashingCellsDefinitions.forEach((flashingCellDefinition) => {
                // for aggregation the data-change needs to be aggChange
                if (dataChangedEvent.trigger !== 'aggChange' &&
                    this.isFlashingTargetOnlyAggChange(flashingCellDefinition)) {
                    return;
                }
                if (flashingCellDefinition.Rule.BooleanExpression) {
                    let expression = flashingCellDefinition.Rule.BooleanExpression;
                    let rowNode = dataChangedEvent.rowNode;
                    if (!rowNode) {
                        rowNode = this.api.gridApi.getRowNodeForPrimaryKey(dataChangedEvent.primaryKeyValue);
                    }
                    const isValidExpression = this.api.expressionApi.isValidBooleanExpression(expression, this.moduleInfo.ModuleName, `Invalid Alert boolean expression '${expression}'`);
                    const isSatisfiedExpression = isValidExpression &&
                        this.api.internalApi
                            .getQueryLanguageService()
                            .evaluateBooleanExpression(expression, this.moduleInfo.ModuleName, rowNode);
                    if (isSatisfiedExpression) {
                        triggeredFlashingCells.push(flashingCellDefinition);
                    }
                }
                else if (this.isAlertPredicateTriggered(flashingCellDefinition, dataChangedEvent, defaultNoPredicateReturn)) {
                    triggeredFlashingCells.push(flashingCellDefinition);
                }
            });
        }
        return triggeredFlashingCells;
    }
    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.api.internalApi.buildBaseContext());
        return this.api.predicateApi.handleColumnPredicates((_a = alert.Rule) === null || _a === void 0 ? void 0 : _a.Predicates, predicateDefHandlerContext, defaultNoPredicateReturn);
    }
    getTeamSharingAction() {
        return {
            ModuleEntities: this.api.flashingCellApi.getFlashingCellDefinitions(),
            AddAction: FlashingCellRedux.FlashingCellDefinitionAdd,
            EditAction: FlashingCellRedux.FlashingCellDefinitionEdit,
        };
    }
    toView(flashingCell) {
        return {
            items: [
                Object.assign(Object.assign({}, (0, getScopeViewItems_1.getScopeViewItems)(flashingCell.Scope, this.api)), { label: 'Trigger' }),
                Object.assign(Object.assign({}, (0, getRuleViewItems_1.getRuleViewItems)(flashingCell.Rule, this.api)), { label: 'Rule', name: 'Rule' }),
                (0, getFlashingCellDurationViewItems_1.getFlashingCellDurationViewItems)(flashingCell),
                (0, getFlashingTargetViewItems_1.getFlashingTargetViewItems)(flashingCell),
                (0, getFlashingCellStyleViewItems_1.getFlashingCellStyleViewItems)(),
                (0, getObjectTagsViewItems_1.getObjectTagsViewItems)(flashingCell, this.api),
            ],
            abObject: flashingCell,
        };
    }
    toViewAll() {
        return this.getModuleAdaptableObjects({
            includeLayoutNotAssociatedObjects: this.showLayoutNotAssociatedObjects(),
        }).map((flashingCell) => this.toView(flashingCell));
    }
    getViewProperties() {
        return {
            getEditAction: FlashingCellRedux.FlashingCellDefinitionEdit,
            getSuspendAction: FlashingCellRedux.FlashingCellDefinitionSuspend,
            getUnSuspendAction: FlashingCellRedux.FlashingCellDefinitionUnSuspend,
            getSuspendAllAction: FlashingCellRedux.FlashingCellDefinitionSuspendAll,
            getUnSuspendAllAction: FlashingCellRedux.FlashingCellDefinitionUnSuspendAll,
            getDeleteAction: FlashingCellRedux.FlashingCellDefinitionDelete,
            getEditWizard: () => FlashingCellWizard_1.FlashingCellWizard,
        };
    }
    canBeAssociatedWithLayouts() {
        return true;
    }
}
exports.FlashingCellModule = FlashingCellModule;
