import * as InternalRedux from '../../Redux/ActionsReducers/InternalRedux';
import * as LayoutRedux from '../../Redux/ActionsReducers/LayoutRedux';
import { ApiBase } from './ApiBase';
import ArrayExtensions from '../../Utilities/Extensions/ArrayExtensions';
import { ColumnFilterInternalApi } from '../Internal/ColumnFilterInternalApi';
import StringExtensions from '../../Utilities/Extensions/StringExtensions';
export class ColumnFilterApiImpl extends ApiBase {
    constructor(_adaptable) {
        super(_adaptable);
        this.internalApi = new ColumnFilterInternalApi(_adaptable);
    }
    getFilterPredicateDefsForColumn(column) {
        if (!column) {
            return [];
        }
        const scope = {
            ColumnIds: [column.columnId],
        };
        return this.getAdaptableApi()
            .predicateApi.internalApi.getFilterPredicateDefs(scope)
            .filter((predicate) => this.getColumnScopeApi().isColumnInScope(column, predicate.columnScope));
    }
    getFilterPredicateDefsForColumnId(columnId) {
        const column = this.getColumnApi().getColumnWithColumnId(columnId);
        return column ? this.getFilterPredicateDefsForColumn(column) : undefined;
    }
    showQuickFilterBar() {
        this.dispatchAction(InternalRedux.QuickFilterBarShow());
    }
    hideQuickFilterBar() {
        this.dispatchAction(InternalRedux.QuickFilterBarHide());
    }
    isQuickFilterAvailable() {
        return this._adaptable.isQuickFilterAvailable();
    }
    isQuickFilterVisible() {
        return (this.isQuickFilterAvailable() &&
            this.getAdaptableInternalApi().getInternalState().IsQuickFilterVisible);
    }
    getColumnFilters() {
        const currentLayout = this.getLayoutApi().getCurrentLayout();
        return currentLayout.ColumnFilters ?? [];
    }
    getActiveColumnFilters() {
        return this.getColumnFilters().filter((columnFilter) => !columnFilter.IsSuspended);
    }
    getColumnFilterDefs() {
        const filters = this.getColumnFilters();
        return filters.map((columnFilter) => {
            const column = this.getColumnApi().getColumnWithColumnId(columnFilter.ColumnId);
            const predicates = columnFilter.Predicates.map((predicate) => this.getPredicateApi().getPredicateDefById(predicate.PredicateId));
            return {
                predicates,
                dataType: column?.dataType,
                columnFilter: columnFilter,
            };
        });
    }
    getColumnFiltersForLayout(layoutName) {
        const layout = this.getLayoutApi().getLayoutByName(layoutName);
        return layout.ColumnFilters ?? [];
    }
    setColumnFilters(columnFilters) {
        columnFilters.forEach((columnFilter) => {
            if (!columnFilter.Predicates || columnFilter.Predicates.length == 0) {
                this.logWarn('Column Filter has no Predicate', columnFilter);
            }
            else {
                const isValidPredicate = this.getPredicateApi().isEveryPredicateValid(columnFilter.Predicates);
                if (!isValidPredicate) {
                    this.logWarn('Column Filter Predicate is not valid', columnFilter);
                }
                else {
                    this.addUidToAdaptableObject(columnFilter);
                    if (this.getColumnFilters().find((cf) => cf.ColumnId == columnFilter.ColumnId)) {
                        this.dispatchAction(LayoutRedux.LayoutColumnFilterSet(columnFilter));
                    }
                    else {
                        this.dispatchAction(LayoutRedux.LayoutColumnFilterAdd(columnFilter));
                    }
                }
            }
        });
        return columnFilters
            ?.map((columnFilter) => this.getColumnFilterById(columnFilter.Uuid))
            .filter(Boolean);
    }
    clearColumnFilter(columnFilter) {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterClear(columnFilter.ColumnId));
    }
    clearColumnFiltersForColumns(columns) {
        columns.forEach((c) => {
            this.clearColumnFilterForColumn(c);
        });
    }
    getColumnFilterForColumn(columnId) {
        return this.getColumnFilters().find((columnFilter) => columnFilter.ColumnId === columnId);
    }
    clearColumnFilterForColumn(columnId) {
        let columnFilterForColumn = this.getColumnFilterForColumn(columnId);
        if (columnFilterForColumn) {
            this.dispatchAction(LayoutRedux.LayoutColumnFilterClear(columnFilterForColumn.ColumnId));
            this._adaptable.clearColumnFilteringForColumns([columnId]);
        }
    }
    clearColumnFilters() {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterClearAll());
        this._adaptable.clearColumnFiltering();
    }
    clearAndSetColumnFilters(columnFilters) {
        this.clearColumnFilters();
        this.setColumnFilters(columnFilters);
    }
    columnFilterToString(columnFilter) {
        if (columnFilter == null) {
            return 'No Column Filter';
        }
        const friendlyName = this.getColumnApi().getFriendlyNameForColumnId(columnFilter.ColumnId);
        return ('[' +
            friendlyName +
            '] ' +
            this.getPredicateApi().predicatesToString(columnFilter.Predicates, columnFilter.PredicatesOperator));
    }
    columnFiltersToString(columnFilters) {
        return columnFilters.map((cf) => this.columnFilterToString(cf)).join(', ');
    }
    getColumnFilterById(id) {
        return this.getColumnFilters()?.find((columnFilter) => columnFilter.Uuid === id);
    }
    isColumnFilterActiveForColumn(columnId) {
        const columnFilter = this.getColumnFilterForColumn(columnId);
        return columnFilter ? this.isColumnFilterActive(columnFilter) : false;
    }
    /**
     * Checks if a filter is applied. It is applied when:
     * - has no inputs
     * - has inputs and inputs have values
     *
     * @param filter
     */
    isColumnFilterActive(filter) {
        if (!filter || !filter.Predicates?.length) {
            return false;
        }
        if (filter.IsSuspended) {
            return false;
        }
        return filter.Predicates.some((predicate) => {
            const predicateDef = this.getPredicateApi().getPredicateDefById(predicate.PredicateId);
            if (ArrayExtensions.IsNull(predicateDef.inputs) &&
                // In and NotIn predicates ave no inputs in the definition
                !this.getPredicateApi().internalApi.IsInOrNotInPredicate(predicate)) {
                return true;
            }
            const inputs = predicate.Inputs || [];
            if (ArrayExtensions.IsEmpty(inputs)) {
                return false;
            }
            // all values in the array need to be non-empty (e.g. between has two values, [min, max])
            const allInputsHaveValues = inputs.every((value) => {
                return value !== undefined && value !== null && value !== '';
            });
            return allInputsHaveValues;
        });
    }
    setColumnFilterForColumn(columnId, columnFilterPredicate) {
        const columnFilter = {
            ColumnId: columnId,
            Predicates: [columnFilterPredicate],
        };
        this.setColumnFilters([columnFilter]);
    }
    clearAndSetColumnFilterForColumn(columnId, columnFilterPredicate) {
        const columnFilter = {
            ColumnId: columnId,
            Predicates: [columnFilterPredicate],
        };
        this.setColumnFilters([columnFilter]);
    }
    suspendColumnFilter(columnFilter) {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterSuspend(columnFilter));
    }
    unSuspendColumnFilter(columnFilter) {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterUnSuspend(columnFilter));
    }
    suspendAllColumnFilters() {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterSuspendAll());
    }
    unSuspendAllColumnFilters() {
        this.dispatchAction(LayoutRedux.LayoutColumnFilterUnSuspendAll());
    }
    addBlanksToInFilterValues(columnDistinctValues) {
        if (columnDistinctValues.some((item) => StringExtensions.IsNullOrEmpty(item.value))) {
            return [
                {
                    label: 'Blanks',
                    value: 'Blanks',
                },
                ...columnDistinctValues,
            ];
        }
        return columnDistinctValues;
    }
    async refreshFilterValues(columnId) {
        const columnFilterHandler = this.getAgGridApi().getColumnFilterHandler(columnId);
        if (!columnFilterHandler ||
            typeof columnFilterHandler.resetFilterDisplayValues !== 'function') {
            this.logWarn(`No filter handler found for column: ${columnId}`);
            return;
        }
        this.logInfo(`Refreshing filter values for column: ${columnId}`);
        return columnFilterHandler.refreshFilterDisplayValues();
    }
    async refreshAllFilterValues() {
        const allFilterHandlers = this.internalApi.getAllAdaptableFilterHandlers();
        const handlerPromises = allFilterHandlers.map(async (handler) => {
            let result = { values: [] };
            if (typeof handler.refreshFilterDisplayValues === 'function') {
                result = await handler.refreshFilterDisplayValues();
            }
            else {
                this.logWarn(`No refresh function for filter handler: ${handler.colId}`);
                result = { values: [] };
            }
            return { columnId: handler.colId, result };
        });
        return Promise.all(handlerPromises).then((results) => {
            return results.reduce((acc, { columnId, result }) => {
                acc[columnId] = result;
                return acc;
            }, {});
        });
    }
    resetFilterValues(columnId) {
        const columnFilterHandler = this.getAgGridApi().getColumnFilterHandler(columnId);
        if (!columnFilterHandler ||
            typeof columnFilterHandler.resetFilterDisplayValues !== 'function') {
            this.logWarn(`No filter handler found for column: ${columnId}`);
            return;
        }
        columnFilterHandler.resetFilterDisplayValues();
    }
    resetAllFilterValues() {
        const allFilterHandlers = this.internalApi.getAllAdaptableFilterHandlers();
        allFilterHandlers.forEach((handler) => {
            if (typeof handler.resetFilterDisplayValues === 'function') {
                handler.resetFilterDisplayValues();
            }
            else {
                this.logWarn(`No reset function for filter handler: ${handler.colId}`);
            }
        });
    }
}
