"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GridInternalApi = void 0;
const tslib_1 = require("tslib");
const Enums_1 = require("../../PredefinedConfig/Common/Enums");
const GridRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/GridRedux"));
const ArrayExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/ArrayExtensions"));
const NumberExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/NumberExtensions"));
const StyleHelper_1 = require("../../Utilities/Helpers/StyleHelper");
const ObjectFactory_1 = require("../../Utilities/ObjectFactory");
const UIHelper_1 = tslib_1.__importDefault(require("../../View/UIHelper"));
const ApiBase_1 = require("../Implementation/ApiBase");
class GridInternalApi extends ApiBase_1.ApiBase {
    /**
     * Fires Grid Sorted Event
     */
    fireGridSortedEvent() {
        if (this.isAdapTableReady()) {
            const adaptableSortState = this.getAdaptableApi().configApi.getAdaptableSortState();
            const adaptableApi = this.getAdaptableApi();
            const gridSortedInfo = Object.assign({ adaptableSortState: adaptableSortState }, this.getAdaptableInternalApi().buildBaseContext());
            adaptableApi.eventApi.emit('GridSorted', gridSortedInfo);
        }
    }
    /**
     * Fires Cell Changed Changed Event - when any data in AG Grid's dataset has changed
     */
    fireCellChangedEvent(cellDataChangedInfo) {
        if (this.isAdapTableReady()) {
            const cellChangedInfo = Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { cellChange: cellDataChangedInfo });
            this.getEventApi().emit('CellChanged', cellChangedInfo);
        }
    }
    /**
     * Fires Grid Data Changed Event - when a row has changed in AG Grid
     */
    fireGridDataChangedEvent(dataRows, rowNodes, rowTrigger) {
        if (this.isAdapTableReady()) {
            const gridDataChangedInfo = Object.assign({ changedAt: Date.now(), rowTrigger,
                dataRows,
                rowNodes }, this.getAdaptableInternalApi().buildBaseContext());
            this.getEventApi().emit('GridDataChanged', gridDataChangedInfo);
            this.getAdaptableInternalApi().getDataService().CreateGridChangedEvent(gridDataChangedInfo);
        }
    }
    /**
     * Gets all distinct display values in the Column for given ColumnId
     * @param columnId Column to check
     */
    getDistinctDisplayValuesForColumn(columnId) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: false,
        };
        const returnValues = this._adaptable.getDistinctValuesForColumn(abColumn, distinctValuesParams);
        return this.sortDistinctValues(returnValues, abColumn).map((cv) => {
            return cv.normalisedValue;
        });
    }
    /**
     * Gets all distinct Filter values for the Column with the given ColumnId
     * used for Floating Filter and Column Header filter
     * either returns a list of values or al ist a list of values with count
     *
     * This is a general method, and it is used in:
     * - Column Filters
     * - Query Builder
     *
     * @param columnId Column to check
     * @param columnFilter Current applied filter
     */
    async getDistinctFilterDisplayValuesForColumn(columnId, filter, showFilteredRowsOnly) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return {
                values: [],
                suppressClientSideFilter: false,
            };
        }
        const distinctValuesParams = {
            visibleRowsOnly: showFilteredRowsOnly,
        };
        const { gridCells, suppressClientSideFilter } = await this.getDistinctFilterListValuesForColumn(abColumn, filter, distinctValuesParams);
        const sortedDistinctValues = this.sortDistinctValues(gridCells, abColumn);
        const shouldShowValuesCount = this.shouldShowValuesCount(abColumn);
        let valueOptions = [];
        if (shouldShowValuesCount) {
            const allGridCells = this._adaptable.getGridCellsForColumn(columnId, this.getColumnFilterOptions().valuesFilterOptions.showCurrentlyFilteredValuesCount);
            const allGridValues = allGridCells.map((gc) => gc.displayValue);
            const newsortedDistinctValues = sortedDistinctValues.filter((gc) => gc.displayValue != undefined && gc.displayValue != '' && gc.displayValue != null);
            valueOptions = newsortedDistinctValues.map((cv) => {
                const label = cv.displayValue +
                    NumberExtensions_1.default.WrapInParentheses(ArrayExtensions_1.default.getOccurrence(allGridValues, cv.displayValue));
                return {
                    label: label,
                    value: cv.normalisedValue,
                };
            });
        }
        else {
            valueOptions = sortedDistinctValues.map((cv) => {
                return {
                    label: cv.displayValue,
                    value: cv.normalisedValue,
                };
            });
        }
        return {
            values: valueOptions,
            suppressClientSideFilter,
        };
    }
    shouldShowValuesCount(column) {
        const showValuesCount = this.getColumnFilterOptions().valuesFilterOptions.showValuesCount;
        let returnValue = false;
        if (showValuesCount) {
            if (typeof showValuesCount === 'function') {
                const columnFilterContext = Object.assign({ column }, this.getAdaptableInternalApi().buildBaseContext());
                returnValue = showValuesCount(columnFilterContext);
            }
            else {
                returnValue = showValuesCount;
            }
        }
        return returnValue;
    }
    async getDistinctFilterDisplayValuesForColumnForFiltersUI(columnId, filter, showFilteredRowsOnly) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (!abColumn) {
            return {
                values: [],
                suppressClientSideFilter: false,
            };
        }
        const shouldShowValuesCount = this.shouldShowValuesCount(abColumn);
        const valueOptions = await this.getDistinctFilterDisplayValuesForColumn(columnId, filter, showFilteredRowsOnly);
        this.addPredicateValues({
            valueOptions: valueOptions.values,
            column: abColumn,
            shouldShowValuesCount,
            visibleRowsOnly: showFilteredRowsOnly,
        });
        return valueOptions;
    }
    addPredicateValues(params) {
        var _a, _b, _c, _d;
        const { valueOptions, column, shouldShowValuesCount, visibleRowsOnly } = params;
        const visibleGridCells = this._adaptable.getGridCellsForColumnTemp(column.columnId, visibleRowsOnly);
        let allGridCells;
        if (shouldShowValuesCount) {
            allGridCells = visibleRowsOnly
                ? visibleGridCells
                : this._adaptable.getGridCellsForColumnTemp(column.columnId, this.getColumnFilterOptions().valuesFilterOptions.showCurrentlyFilteredValuesCount);
        }
        const adaptableApi = this.getAdaptableApi();
        const predicateIds = adaptableApi.columnFilterApi.internalApi.getValuesFitlerPredicateIds(column);
        if (ArrayExtensions_1.default.IsNullOrEmpty(predicateIds)) {
            return;
        }
        const predicatesPosition = (_d = (_c = (_b = (_a = adaptableApi.optionsApi.getColumnFilterOptions()) === null || _a === void 0 ? void 0 : _a.valuesFilterOptions) === null || _b === void 0 ? void 0 : _b.valuesFilterPredicateOptions) === null || _c === void 0 ? void 0 : _c.predicatesPosition) !== null && _d !== void 0 ? _d : 'Start';
        const predicateValues = predicateIds
            .filter((predicateId) => {
            // we have to make sure it is part of the visibleRowsOnly, when true
            if (!visibleRowsOnly) {
                return true;
            }
            return this.isPredicateInVisibleCellValues(predicateId, visibleGridCells);
        })
            .map((predicateId) => {
            var _a;
            const predicateDef = adaptableApi.predicateApi.getPredicateDefById(predicateId);
            let label = ((_a = predicateDef.label) !== null && _a !== void 0 ? _a : predicateId);
            return {
                value: predicateId,
                label: shouldShowValuesCount
                    ? label +
                        NumberExtensions_1.default.WrapInParentheses(this.getPredicateOccurance({ predicateId, column, allGridCells }))
                    : label,
            };
        });
        if (predicatesPosition === 'End') {
            valueOptions.push(...predicateValues);
        }
        else {
            valueOptions.unshift(...predicateValues);
        }
    }
    isPredicateInVisibleCellValues(predicateId, allGridCells) {
        const predicate = this.getPredicateApi().getPredicateDefById(predicateId);
        if (!predicate) {
            return false;
        }
        const commonContext = (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi());
        for (let gridCell of allGridCells) {
            if (this.getPredicateApi().handlePredicate({
                PredicateId: predicate.id,
            }, Object.assign({ value: gridCell.rawValue, oldValue: null, displayValue: gridCell.displayValue, node: gridCell.rowNode, column: gridCell.column }, commonContext), false)) {
                return true;
            }
        }
        return false;
    }
    getPredicateOccurance(params) {
        const { predicateId, allGridCells, column } = params;
        const predicate = this.getPredicateApi().getPredicateDefById(predicateId);
        if (!predicate) {
            return 0;
        }
        let count = 0;
        const commonContext = (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi());
        for (let gridCell of allGridCells) {
            if (this.getPredicateApi().handlePredicate({
                PredicateId: predicate.id,
            }, Object.assign({ value: gridCell.rawValue, oldValue: null, displayValue: gridCell.displayValue, node: gridCell.rowNode, column }, commonContext), false)) {
                count++;
            }
        }
        return count;
    }
    async getDistinctFilterListValuesForColumn(column, filter, distinctValuesParams) {
        var _a;
        const filterPermittedValues = (_a = this.getUserInterfaceApi().getFilterPermittedValuesForColumn(column)) !== null && _a !== void 0 ? _a : {
            suppressFilterSearchBar: false,
            values: () => undefined,
        };
        let preparedPermittedValues = undefined;
        try {
            const filterPermittedValuesParams = Object.assign(Object.assign({}, (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi())), { column: column, searchFilter: filter });
            preparedPermittedValues = await (filterPermittedValues === null || filterPermittedValues === void 0 ? void 0 : filterPermittedValues.values(filterPermittedValuesParams));
        }
        catch (error) {
            this._adaptable.logger.consoleError(`Failed to load filter permitted values`, column, filter, error);
        }
        distinctValuesParams.permittedValues = preparedPermittedValues;
        return {
            suppressClientSideFilter: filterPermittedValues.suppressFilterSearchBar,
            gridCells: this._adaptable.getDistinctValuesForColumn(column, distinctValuesParams),
        };
    }
    /**
     * Gets all distinct Custom Sort values for the Column with the given ColumnId
     * @param columnId Column to check
     */
    async getDistinctCustomSortDisplayValuesForColumn(columnId) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: false,
        };
        const gridCells = await this.getDistinctCustomSortValuesForColumn(abColumn, distinctValuesParams);
        return this.sortDistinctValues(gridCells, abColumn).map((cv) => {
            return cv.normalisedValue;
        });
    }
    async getDistinctCustomSortValuesForColumn(column, distinctValuesParams) {
        const customSortPermittedValues = await this.getUserInterfaceApi().getCustomSortPermittedValuesForColumn(column);
        let preparedPermittedValues = undefined;
        try {
            const permittedValuesParams = Object.assign(Object.assign({}, (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi())), { column: column });
            preparedPermittedValues = await (customSortPermittedValues === null || customSortPermittedValues === void 0 ? void 0 : customSortPermittedValues.values(permittedValuesParams));
        }
        catch (error) {
            this._adaptable.logger.consoleError(`Failed to load custom sort permitted values`, column, error);
        }
        distinctValuesParams.permittedValues = preparedPermittedValues;
        return this._adaptable.getDistinctValuesForColumn(column, distinctValuesParams);
    }
    /**
     * Gets all distinct Bulk Update values for the Column with the given ColumnId
     * @param columnId Column to check
     * @param selectedGridCells Selected grid cells
     */
    async getDistinctBulkUpdateDisplayValuesForColumn(columnId, selectedGridCells) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: false,
        };
        const gridCells = await this.getDistinctBulkUpdateValuesForColumn(abColumn, selectedGridCells, distinctValuesParams);
        return this.sortDistinctValues(gridCells, abColumn).map((cv) => {
            return cv.normalisedValue;
        });
    }
    async getDistinctBulkUpdateValuesForColumn(column, selectedGridCells, distinctValuesParams) {
        const bulkUpdatePermittedValues = await this.getUserInterfaceApi().getBulkUpdatePermittedValuesForColumn(column);
        let preparedPermittedValues = undefined;
        try {
            const bulkUpdatePermittedValuesParams = Object.assign(Object.assign({}, (0, ObjectFactory_1.createBaseContext)(this.getAdaptableApi())), { column: column, gridCells: selectedGridCells });
            preparedPermittedValues = await (bulkUpdatePermittedValues === null || bulkUpdatePermittedValues === void 0 ? void 0 : bulkUpdatePermittedValues.values(bulkUpdatePermittedValuesParams));
        }
        catch (error) {
            this._adaptable.logger.consoleError(`Failed to load bulk permitted values`, error, column, selectedGridCells);
        }
        distinctValuesParams.permittedValues = preparedPermittedValues;
        return this._adaptable.getDistinctValuesForColumn(column, distinctValuesParams);
    }
    /**
     * Gets all distinct visible (after current filters are applied) display values in the Column with the given ColumnId
     * @param columnId Column to check
     */
    getDistinctVisibleDisplayValuesForColumn(columnId) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: true,
        };
        const returnValues = this._adaptable.getDistinctValuesForColumn(abColumn, distinctValuesParams);
        return this.sortDistinctValues(returnValues, abColumn).map((cv) => {
            return cv.normalisedValue;
        });
    }
    /**
     * Gets all distinct raw values in Column. Values are sorted.
     * @param columnId Column to check
     * @param skipRowNode optional RowNode which should be skipped when collecting the distinct rawValues
     */
    getDistinctRawValuesForColumn(columnId, skipRowNode) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        return this.sortDistinctValues(this.getUnsortedDistinctRawValuesForColumn(columnId, skipRowNode), abColumn).map((cv) => {
            return cv.rawValue;
        });
    }
    /**
     * Gets all distinct raw values in Column. Values are un-sorted.
     * @param columnId Column to check
     * @param skipRowNode optional RowNode which should be skipped when collecting the distinct rawValues
     */
    getUnsortedDistinctRawValuesForColumn(columnId, skipRowNode) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: false,
            skipRowNode: skipRowNode,
        };
        return this._adaptable.getDistinctValuesForColumn(abColumn, distinctValuesParams);
    }
    /**
     * Gets all distinct visible raw values in the Column
     * @param columnId Column to check
     */
    getDistinctVisibleRawValuesForColumn(columnId) {
        const abColumn = this.getColumnApi().getColumnWithColumnId(columnId);
        if (abColumn == undefined) {
            return [];
        }
        const distinctValuesParams = {
            visibleRowsOnly: true,
        };
        const returnValues = this._adaptable.getDistinctValuesForColumn(abColumn, distinctValuesParams);
        return this.sortDistinctValues(returnValues, abColumn).map((cv) => {
            return cv.rawValue;
        });
    }
    sortDistinctValues(returnValues, column) {
        // this does NOT into account Custom Sort - far too hard for now...
        let sortOrder = Enums_1.SortOrder.Asc;
        if (this.getColumnFilterOptions().valuesFilterOptions.sortValuesFilter) {
            let columnSort = this.getGridApi().getColumnSortForColumn(column.columnId);
            if (columnSort && columnSort.SortOrder == 'Desc') {
                sortOrder = Enums_1.SortOrder.Desc;
            }
        }
        if (this.getColumnApi().hasNumberDataType(column === null || column === void 0 ? void 0 : column.columnId)) {
            returnValues = ArrayExtensions_1.default.sortCellValueArrayNumeric(returnValues, sortOrder);
        }
        else if (this.getColumnApi().hasDateDataType(column === null || column === void 0 ? void 0 : column.columnId)) {
            returnValues = ArrayExtensions_1.default.sortCellValueArrayDates(returnValues, sortOrder);
        }
        else {
            returnValues = ArrayExtensions_1.default.sortCellValueArray(returnValues, sortOrder);
        }
        return returnValues;
    }
    setColumns(columns) {
        this.dispatchAction(GridRedux.GridSetColumns(columns));
    }
    setSelectedCells(selectedCellInfo) {
        this.dispatchAction(GridRedux.GridSetSelectedCells(selectedCellInfo));
    }
    setSelectedRows(selectedRowInfo) {
        this.dispatchAction(GridRedux.GridSetSelectedRows(selectedRowInfo));
    }
    buildStandaloneColumnHeader(column) {
        return this._adaptable.agGridMenuAdapter.buildStandaloneColumnHeader(column);
    }
    getEditLookUpValuesForColumn(editLookUpItem, column, gridCell) {
        if (!editLookUpItem || !column) {
            return undefined;
        }
        let editLookUpValues = editLookUpItem.values;
        // first do the function then get hardcoded items
        if (editLookUpValues != null && typeof editLookUpValues === 'function') {
            const editLookUpContext = Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { column: column, gridCell });
            return editLookUpValues(editLookUpContext);
        }
        else {
            let arr = editLookUpValues;
            if (arr && ArrayExtensions_1.default.IsNotNullOrEmpty(arr)) {
                return arr;
            }
        }
        // if no hard-coded values or function provided then just get the distinct values for the column
        // this will use the columnApi method that first looks for permitted values and then distinct values
        return this.getDistinctDisplayValuesForColumn(column.columnId);
    }
    getAgGridDataType(dataType) {
        if (!dataType) {
            return 'abColDefString';
        }
        switch (dataType) {
            case 'Boolean':
                return 'abColDefBoolean';
            case 'Date':
                return 'abColDefDate';
            case 'Number':
                return 'abColDefNumber';
            case 'Object':
                return 'abColDefObject';
            case 'String':
                return 'abColDefString';
            case 'NumberArray':
                return 'abColDefNumberArray';
            case 'TupleNumberArray':
                return 'abColDefTupleNumberArray';
            case 'ObjectNumberArray':
                return 'abColDefObjectNumberArray';
            default:
                return 'abColDefCustom';
        }
    }
    getRowHighlightStyle(params) {
        var _a;
        const primaryKeyValue = this._adaptable.getPrimaryKeyValueFromRowNode(params.node, params.api);
        const highlightRow = (_a = this.getAdaptableApi()
            .internalApi.getSystemState()
            .HighlightedRows) === null || _a === void 0 ? void 0 : _a.find((highlightRow) => {
            return highlightRow.primaryKeyValue === primaryKeyValue;
        });
        if (highlightRow) {
            return (0, StyleHelper_1.convertAdaptableStyleToCSS)(highlightRow.highlightStyle);
        }
    }
    getAlertRowStyle(params) {
        var _a, _b;
        const alert = this.getAlertApi().internalApi.getAdaptableAlertWithHighlightRow(params.node);
        const highlightRow = (_b = (_a = alert === null || alert === void 0 ? void 0 : alert.alertDefinition) === null || _a === void 0 ? void 0 : _a.AlertProperties) === null || _b === void 0 ? void 0 : _b.HighlightRow;
        if (highlightRow) {
            return typeof highlightRow === 'object'
                ? (0, StyleHelper_1.convertAdaptableStyleToCSS)(highlightRow)
                : {
                    backgroundColor: UIHelper_1.default.getColorByMessageType(alert.alertDefinition.MessageType),
                };
        }
        return null;
    }
    getAlertRowClass(params) {
        var _a, _b;
        const alert = this.getAlertApi().internalApi.getAdaptableAlertWithHighlightRow(params.node);
        const highlightRow = (_b = (_a = alert === null || alert === void 0 ? void 0 : alert.alertDefinition) === null || _a === void 0 ? void 0 : _a.AlertProperties) === null || _b === void 0 ? void 0 : _b.HighlightRow;
        return typeof highlightRow === 'object' && (highlightRow === null || highlightRow === void 0 ? void 0 : highlightRow.ClassName)
            ? highlightRow === null || highlightRow === void 0 ? void 0 : highlightRow.ClassName
            : null;
    }
    getRowHighlightClass(params) {
        var _a;
        const primaryKeyValue = this._adaptable.getPrimaryKeyValueFromRowNode(params.node, params.api);
        const highlightRow = (_a = this.getAdaptableApi()
            .internalApi.getSystemState()
            .HighlightedRows) === null || _a === void 0 ? void 0 : _a.find((highlightRow) => {
            return highlightRow.primaryKeyValue === primaryKeyValue;
        });
        return typeof (highlightRow === null || highlightRow === void 0 ? void 0 : highlightRow.highlightStyle) === 'object'
            ? highlightRow.highlightStyle.ClassName
            : null;
    }
    deriveSpecialColumnSettingsFromAgGridDefaultColDef() {
        const defaultColumnDefinition = this._adaptable.agGridAdapter.getDefaultColumnDefinition();
        return {
            Filterable: defaultColumnDefinition.filter,
            Resizable: defaultColumnDefinition.resizable,
            Groupable: defaultColumnDefinition.enableRowGroup,
            Sortable: defaultColumnDefinition.sortable,
            Pivotable: defaultColumnDefinition.enablePivot,
            Aggregatable: defaultColumnDefinition.enableValue,
            SuppressMenu: defaultColumnDefinition.suppressHeaderMenuButton,
            SuppressMovable: defaultColumnDefinition.suppressMovable,
            HeaderToolTip: defaultColumnDefinition.headerTooltip,
            Width: defaultColumnDefinition.width,
        };
    }
    hasCellEditableAccordingToEditOptions() {
        var _a;
        return typeof ((_a = this.getEditOptions()) === null || _a === void 0 ? void 0 : _a.isCellEditable) === 'function';
    }
    /**
     * Returns UNDEFINED if no EditOptions.isCellEditable is provided, otherwise returns the result of the function
     *
     * DO NOT USE THIS METHOD DIRECTLY - use `GridApi.isCellEditable` instead
     */
    isCellEditableAccordingToEditOptions(gridCell, defaultColDefinitionEditableValue) {
        var _a;
        const cellEditable = (_a = this.getEditOptions()) === null || _a === void 0 ? void 0 : _a.isCellEditable;
        if (cellEditable) {
            const cellEditableContext = Object.assign(Object.assign({}, this.getAdaptableInternalApi().buildBaseContext()), { gridCell, defaultColDefEditableValue: defaultColDefinitionEditableValue });
            return cellEditable(cellEditableContext);
        }
        return undefined;
    }
}
exports.GridInternalApi = GridInternalApi;
