"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFilterRuleDefinedForFieldId = exports.compressDashboardFiltersToParam = exports.convertDashboardFiltersParamToDashboardFilters = exports.convertDashboardFiltersToFilters = exports.FilterGroupOperator = exports.isDashboardFilterRule = exports.applyDimensionOverrides = exports.removeFieldFromFilterGroup = exports.updateFieldIdInFilters = exports.updateFieldIdInFilterGroupItem = exports.getFilterRules = exports.flattenFilterGroup = exports.isMetricFilterTarget = exports.isFilterTarget = exports.isFilterRule = exports.isFilterGroup = exports.isAndFilterGroup = exports.isOrFilterGroup = exports.isDateFilterRule = exports.isDashboardFieldTarget = exports.isJoinModelRequiredFilter = exports.getUnitsOfTimeGreaterOrEqual = exports.unitOfTimeFormat = exports.UnitOfTime = exports.FilterOperator = exports.FilterType = void 0;
var FilterType;
(function (FilterType) {
    FilterType["STRING"] = "string";
    FilterType["NUMBER"] = "number";
    FilterType["DATE"] = "date";
    FilterType["BOOLEAN"] = "boolean";
})(FilterType || (exports.FilterType = FilterType = {}));
var FilterOperator;
(function (FilterOperator) {
    FilterOperator["NULL"] = "isNull";
    FilterOperator["NOT_NULL"] = "notNull";
    FilterOperator["EQUALS"] = "equals";
    FilterOperator["NOT_EQUALS"] = "notEquals";
    FilterOperator["STARTS_WITH"] = "startsWith";
    FilterOperator["ENDS_WITH"] = "endsWith";
    FilterOperator["INCLUDE"] = "include";
    FilterOperator["NOT_INCLUDE"] = "doesNotInclude";
    FilterOperator["LESS_THAN"] = "lessThan";
    FilterOperator["LESS_THAN_OR_EQUAL"] = "lessThanOrEqual";
    FilterOperator["GREATER_THAN"] = "greaterThan";
    FilterOperator["GREATER_THAN_OR_EQUAL"] = "greaterThanOrEqual";
    FilterOperator["IN_THE_PAST"] = "inThePast";
    FilterOperator["NOT_IN_THE_PAST"] = "notInThePast";
    FilterOperator["IN_THE_NEXT"] = "inTheNext";
    FilterOperator["IN_THE_CURRENT"] = "inTheCurrent";
    FilterOperator["NOT_IN_THE_CURRENT"] = "notInTheCurrent";
    FilterOperator["IN_BETWEEN"] = "inBetween";
    FilterOperator["NOT_IN_BETWEEN"] = "notInBetween";
    FilterOperator["IN_PERIOD_TO_DATE"] = "inPeriodToDate";
})(FilterOperator || (exports.FilterOperator = FilterOperator = {}));
var UnitOfTime;
(function (UnitOfTime) {
    UnitOfTime["milliseconds"] = "milliseconds";
    UnitOfTime["seconds"] = "seconds";
    UnitOfTime["minutes"] = "minutes";
    UnitOfTime["hours"] = "hours";
    UnitOfTime["days"] = "days";
    UnitOfTime["weeks"] = "weeks";
    UnitOfTime["months"] = "months";
    UnitOfTime["quarters"] = "quarters";
    UnitOfTime["years"] = "years";
})(UnitOfTime || (exports.UnitOfTime = UnitOfTime = {}));
exports.unitOfTimeFormat = {
    milliseconds: 'YYYY-MM-DD HH:mm:ss',
    seconds: 'YYYY-MM-DD HH:mm:ss',
    minutes: 'YYYY-MM-DD HH:mm',
    hours: 'YYYY-MM-DD HH',
    days: 'YYYY-MM-DD',
    weeks: 'YYYY-MM-DD',
    months: 'YYYY-MM',
    quarters: 'YYYY-MM',
    years: 'YYYY',
};
const getUnitsOfTimeGreaterOrEqual = (unit) => {
    const unitsInOrder = [
        UnitOfTime.milliseconds,
        UnitOfTime.seconds,
        UnitOfTime.minutes,
        UnitOfTime.hours,
        UnitOfTime.days,
        UnitOfTime.weeks,
        UnitOfTime.months,
        UnitOfTime.quarters,
        UnitOfTime.years,
    ];
    const index = unitsInOrder.indexOf(unit);
    if (index === -1) {
        // return the original array if the unit is not found
        return unitsInOrder;
    }
    return unitsInOrder.slice(index);
};
exports.getUnitsOfTimeGreaterOrEqual = getUnitsOfTimeGreaterOrEqual;
const isJoinModelRequiredFilter = (filter) => 'tableName' in filter.target;
exports.isJoinModelRequiredFilter = isJoinModelRequiredFilter;
const isDashboardFieldTarget = (target) => target !== null &&
    typeof target === 'object' &&
    'fieldId' in target &&
    'tableName' in target;
exports.isDashboardFieldTarget = isDashboardFieldTarget;
const isDateFilterRule = (filter) => 'unitOfTime' in (filter.settings || {});
exports.isDateFilterRule = isDateFilterRule;
/* Utils */
const isOrFilterGroup = (value) => 'or' in value;
exports.isOrFilterGroup = isOrFilterGroup;
const isAndFilterGroup = (value) => 'and' in value;
exports.isAndFilterGroup = isAndFilterGroup;
const isFilterGroup = (value) => (0, exports.isOrFilterGroup)(value) || (0, exports.isAndFilterGroup)(value);
exports.isFilterGroup = isFilterGroup;
const isFilterRule = (value) => 'id' in value && 'target' in value && 'operator' in value;
exports.isFilterRule = isFilterRule;
const isFilterTarget = (value) => !!value && typeof value === 'object' && 'fieldId' in value;
exports.isFilterTarget = isFilterTarget;
const isMetricFilterTarget = (value) => !!value && typeof value === 'object' && 'fieldRef' in value;
exports.isMetricFilterTarget = isMetricFilterTarget;
const flattenFilterGroup = (filterGroup) => {
    // Explicitly checking for undefined filter groups (and || or), saved filter group somehow was undefined when saving
    const groupItems = (0, exports.isAndFilterGroup)(filterGroup)
        ? filterGroup.and
        : filterGroup.or;
    return (groupItems || []).flatMap((item) => {
        if ((0, exports.isFilterGroup)(item)) {
            return (0, exports.flattenFilterGroup)(item);
        }
        return [item];
    });
};
exports.flattenFilterGroup = flattenFilterGroup;
const getFilterRules = (filters) => {
    const rules = [];
    if (filters.dimensions) {
        rules.push(...(0, exports.flattenFilterGroup)(filters.dimensions));
    }
    if (filters.metrics) {
        rules.push(...(0, exports.flattenFilterGroup)(filters.metrics));
    }
    if (filters.tableCalculations) {
        rules.push(...(0, exports.flattenFilterGroup)(filters.tableCalculations));
    }
    return rules;
};
exports.getFilterRules = getFilterRules;
const updateFieldIdInFilterGroupItem = (filterGroupItem, previousName, newName) => {
    if ((0, exports.isFilterGroup)(filterGroupItem)) {
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        (0, exports.updateFieldIdInFilters)(filterGroupItem, previousName, newName);
    }
    else if (filterGroupItem.target.fieldId === previousName) {
        // eslint-disable-next-line no-param-reassign
        filterGroupItem.target.fieldId = newName;
    }
};
exports.updateFieldIdInFilterGroupItem = updateFieldIdInFilterGroupItem;
const updateFieldIdInFilters = (filterGroup, previousName, newName) => {
    if (filterGroup) {
        if ((0, exports.isOrFilterGroup)(filterGroup)) {
            filterGroup.or.forEach((item) => (0, exports.updateFieldIdInFilterGroupItem)(item, previousName, newName));
        }
        else if ((0, exports.isAndFilterGroup)(filterGroup)) {
            filterGroup.and.forEach((item) => (0, exports.updateFieldIdInFilterGroupItem)(item, previousName, newName));
        }
    }
};
exports.updateFieldIdInFilters = updateFieldIdInFilters;
const removeFieldFromFilterGroup = (filterGroup, fieldId) => {
    if (!filterGroup) {
        return undefined;
    }
    const removeFiltersGroupItems = (items) => items.reduce((acc, item) => {
        if ((0, exports.isFilterGroup)(item)) {
            const updatedGroup = (0, exports.removeFieldFromFilterGroup)(item, fieldId); // remove field from filter groups recursively
            if (updatedGroup) {
                acc.push(updatedGroup);
            }
        }
        else if (item.target.fieldId !== fieldId) {
            // keep filter rule if fieldId does not match
            acc.push(item);
        }
        return acc;
    }, []);
    if ((0, exports.isOrFilterGroup)(filterGroup)) {
        const updatedItems = removeFiltersGroupItems(filterGroup.or);
        if (updatedItems.length === 0) {
            return undefined;
        }
        return {
            ...filterGroup,
            or: updatedItems,
        };
    }
    const updatedItems = removeFiltersGroupItems(filterGroup.and);
    if (updatedItems.length === 0) {
        return undefined;
    }
    return {
        ...filterGroup,
        and: updatedItems,
    };
};
exports.removeFieldFromFilterGroup = removeFieldFromFilterGroup;
const applyDimensionOverrides = (dashboardFilters, overrides) => {
    const overrideArray = overrides instanceof Array ? overrides : overrides.dimensions;
    // Apply overrides to existing dashboard dimensions
    const overriddenDimensions = dashboardFilters.dimensions.map((dimension) => {
        const override = overrideArray.find((overrideDimension) => overrideDimension.id === dimension.id);
        if (override) {
            return {
                ...override,
                tileTargets: dimension.tileTargets,
                // Lock state belongs to the saved dashboard and must not
                // be assertable from URL/scheduler overrides — always
                // re-apply the saved rule's lockedTabUuids.
                lockedTabUuids: dimension.lockedTabUuids,
            };
        }
        return dimension;
    });
    // Add scheduler filters that don't exist in dashboard saved filters
    const existingIds = new Set(dashboardFilters.dimensions.map((d) => d.id));
    const newDimensions = overrideArray.filter((schedulerFilter) => !existingIds.has(schedulerFilter.id));
    overriddenDimensions.push(...newDimensions);
    return overriddenDimensions;
};
exports.applyDimensionOverrides = applyDimensionOverrides;
const isDashboardFilterRule = (value) => (0, exports.isFilterRule)(value) && 'tableName' in value.target;
exports.isDashboardFilterRule = isDashboardFilterRule;
var FilterGroupOperator;
(function (FilterGroupOperator) {
    FilterGroupOperator["and"] = "and";
    FilterGroupOperator["or"] = "or";
})(FilterGroupOperator || (exports.FilterGroupOperator = FilterGroupOperator = {}));
const convertDashboardFiltersToFilters = (dashboardFilters) => {
    const { dimensions, metrics, tableCalculations } = dashboardFilters;
    const filters = {};
    if (dimensions.length > 0) {
        filters.dimensions = {
            id: 'dashboard_dimension_filters',
            and: dimensions.map((dimension) => dimension),
        };
    }
    if (metrics.length > 0) {
        filters.metrics = {
            id: 'dashboard_dimension_metrics',
            and: metrics.map((metric) => metric),
        };
    }
    if (tableCalculations.length > 0) {
        filters.tableCalculations = {
            id: 'dashboard_tablecalculation_filters',
            and: tableCalculations.map((tableCalculation) => tableCalculation),
        };
    }
    return filters;
};
exports.convertDashboardFiltersToFilters = convertDashboardFiltersToFilters;
const isDashboardTileTargetFilterOverride = (filter) => typeof filter === 'object' || typeof filter === 'boolean';
const convertDashboardFiltersParamToDashboardFilters = (dashboardFilters) => Object.entries(dashboardFilters).reduce((result, [key, value]) => ({
    ...result,
    [key]: value.map((f) => ({
        ...f,
        ...(f.tileTargets && {
            tileTargets: f.tileTargets.reduce((tileTargetsResult, tileTarget) => {
                const targetName = Object.keys(tileTarget)[0];
                const targetValue = Object.values(tileTarget)[0];
                if (isDashboardTileTargetFilterOverride(tileTarget)) {
                    return {
                        ...tileTargetsResult,
                        ...{ [targetName]: targetValue },
                    };
                }
                return tileTargetsResult;
            }, {}),
        }),
    })),
}), { dimensions: [], metrics: [], tableCalculations: [] });
exports.convertDashboardFiltersParamToDashboardFilters = convertDashboardFiltersParamToDashboardFilters;
const compressDashboardFiltersToParam = (dashboardFilters) => Object.entries(dashboardFilters).reduce((result, [key, value]) => ({
    ...result,
    [key]: value.map((f) => ({
        ...f,
        ...(f.tileTargets && {
            tileTargets: Object.entries(f.tileTargets).reduce((tileTargetsResult, [tileTargetKey, tileTargetValue]) => {
                // If the filter is not disabled for this tile
                // AND the table and field match, we omit it.
                // The filter will be automatically applied there
                if (tileTargetValue !== false &&
                    (0, exports.isDashboardFieldTarget)(tileTargetValue) &&
                    tileTargetValue.fieldId === f.target.fieldId &&
                    tileTargetValue.tableName === f.target.tableName) {
                    return tileTargetsResult;
                }
                return [
                    ...tileTargetsResult,
                    {
                        [tileTargetKey]: tileTargetValue,
                    },
                ];
            }, []),
        }),
    })),
}), { dimensions: [], metrics: [], tableCalculations: [] });
exports.compressDashboardFiltersToParam = compressDashboardFiltersToParam;
const isFilterRuleDefinedForFieldId = (filterGroup, fieldId, isInterval = false) => {
    // Check if the filter group is an 'and' or 'or' group
    const filterGroupItems = (0, exports.isAndFilterGroup)(filterGroup)
        ? filterGroup.and
        : filterGroup.or;
    // If the item is a filter rule, check if its id matches the provided filter rule id
    const isMatchingFieldId = (item) => {
        if (!(0, exports.isFilterGroup)(item)) {
            // If the item is not a filter group, check if it matches the fieldId
            return isInterval
                ? item.target.fieldId.startsWith(fieldId)
                : item.target.fieldId === fieldId;
        }
        return false;
    };
    const isFilterRulePresent = (item) => {
        if (isMatchingFieldId(item)) {
            return true;
        }
        if ((0, exports.isFilterGroup)(item)) {
            // If the item is a filter group, recursively check its items
            return (0, exports.isFilterRuleDefinedForFieldId)(item, fieldId, isInterval);
        }
        return false;
    };
    // If the filter rule was not found in the filter group, return false
    return filterGroupItems.some(isFilterRulePresent);
};
exports.isFilterRuleDefinedForFieldId = isFilterRuleDefinedForFieldId;
//# sourceMappingURL=filter.js.map