"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SystemBadgeStylePredicateIds = exports.SystemFlashingCellPredicateIds = exports.SystemFormatColumnPredicateIds = exports.SystemAlertPredicateIds = exports.SystemFilterPredicateIds = exports.SystemPredicateDefs = void 0;
const tslib_1 = require("tslib");
const isAfter_1 = tslib_1.__importDefault(require("date-fns/isAfter"));
const isBefore_1 = tslib_1.__importDefault(require("date-fns/isBefore"));
const isEqual_1 = tslib_1.__importDefault(require("date-fns/isEqual"));
const isFuture_1 = tslib_1.__importDefault(require("date-fns/isFuture"));
const isPast_1 = tslib_1.__importDefault(require("date-fns/isPast"));
const isSameDay_1 = tslib_1.__importDefault(require("date-fns/isSameDay"));
const isThisMonth_1 = tslib_1.__importDefault(require("date-fns/isThisMonth"));
const isThisQuarter_1 = tslib_1.__importDefault(require("date-fns/isThisQuarter"));
const isThisWeek_1 = tslib_1.__importDefault(require("date-fns/isThisWeek"));
const isThisYear_1 = tslib_1.__importDefault(require("date-fns/isThisYear"));
const isToday_1 = tslib_1.__importDefault(require("date-fns/isToday"));
const isTomorrow_1 = tslib_1.__importDefault(require("date-fns/isTomorrow"));
const isYesterday_1 = tslib_1.__importDefault(require("date-fns/isYesterday"));
const StringExtensions_1 = tslib_1.__importDefault(require("../../Utilities/Extensions/StringExtensions"));
const DateHelper_1 = require("../../Utilities/Helpers/DateHelper");
const Helper_1 = tslib_1.__importDefault(require("../../Utilities/Helpers/Helper"));
const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
/**
 * Array of Predicate Defs which are shipped by AdapTable
 */
exports.SystemPredicateDefs = [
    {
        id: 'Values',
        label: 'Values',
        icon: { text: 'IN' },
        columnScope: { DataTypes: ['String', 'Number', 'Date'] },
        moduleScope: ['columnFilter', 'flashingcell', 'formatColumn', 'alert', 'badgeStyle'],
        handler: (context) => {
            const { inputs, column, value, adaptableApi } = context;
            const predicateInputs = context.inputs.reduce((acc, input) => {
                const predicate = adaptableApi.predicateApi.getPredicateDefById(input);
                if (predicate) {
                    acc.push(predicate);
                }
                return acc;
            }, []);
            if (predicateInputs.length) {
                const nestedContext = Object.assign({}, context);
                delete nestedContext.inputs;
                const predicateResult = predicateInputs.some((predicate) => {
                    return adaptableApi.predicateApi.handlePredicate({
                        PredicateId: predicate.id,
                    }, nestedContext, false);
                });
                if (predicateResult) {
                    // We want to use the only true values, to allow for multiple predicates to be used
                    return predicateResult;
                }
            }
            if (inputs.length === 0) {
                return true;
            }
            if (inputs.includes(GeneralConstants_1.BLANK_DISTINCT_COLUMN_VALUE) && Helper_1.default.isInputNullOrEmpty(value)) {
                return true;
            }
            if (column.dataType === 'Date') {
                return inputs.some((input) => {
                    if (adaptableApi.optionsApi.getColumnFilterOptions().valuesFilterOptions
                        .filterValuesUsingTime) {
                        return (0, isEqual_1.default)(input, value);
                    }
                    else {
                        return (0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(input), (0, DateHelper_1.parseDateValue)(value));
                    }
                });
            }
            if (column.dataType === 'Number') {
                return inputs.includes(value);
            }
            if (column.dataType === 'String') {
                return adaptableApi.predicateApi.useCaseSensitivity()
                    ? inputs
                        .map((i) => {
                        return i === null || i === void 0 ? void 0 : i.toLocaleLowerCase();
                    })
                        .includes(value === null || value === void 0 ? void 0 : value.toLocaleLowerCase())
                    : inputs.includes(value);
            }
            return true;
        },
        toString: ({ inputs }) => `IN (${inputs.join(', ')})`,
        shortcuts: ['#', '['],
    },
    {
        id: 'ExcludeValues',
        label: 'Exclude Values',
        icon: { text: '!IN' },
        columnScope: { DataTypes: ['String', 'Number', 'Date'] },
        moduleScope: ['columnFilter', 'flashingcell', 'formatColumn', 'alert', 'badgeStyle'],
        handler: ({ inputs, column, value, adaptableApi }) => {
            // basically negation of IN
            if (inputs.length === 0) {
                return true;
            }
            if (inputs.includes(GeneralConstants_1.BLANK_DISTINCT_COLUMN_VALUE) && Helper_1.default.isInputNullOrEmpty(value)) {
                return false;
            }
            if (column.dataType === 'Date') {
                if (adaptableApi.optionsApi.getColumnFilterOptions().valuesFilterOptions.filterValuesUsingTime) {
                    return inputs.every((input) => {
                        return !(0, isEqual_1.default)(input, value);
                    });
                }
                else {
                    return inputs.every((input) => {
                        return !(0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(input), (0, DateHelper_1.parseDateValue)(value));
                    });
                }
            }
            if (column.dataType === 'Number') {
                return !inputs.includes(value);
            }
            if (column.dataType === 'String') {
                return adaptableApi.predicateApi.useCaseSensitivity()
                    ? !inputs
                        .map((i) => {
                        return i === null || i === void 0 ? void 0 : i.toLocaleLowerCase();
                    })
                        .includes(value === null || value === void 0 ? void 0 : value.toLocaleLowerCase())
                    : !inputs.includes(value);
            }
            return true;
        },
        toString: ({ inputs }) => `Exclude (${inputs.join(', ')})`,
    },
    {
        id: 'Blanks',
        label: 'Blanks',
        icon: { name: 'unfilled-circle' },
        columnScope: { All: true },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        handler: ({ value }) => Helper_1.default.isInputNullOrEmpty(value),
    },
    {
        id: 'NonBlanks',
        label: 'Non Blanks',
        icon: { name: 'filled-circle' },
        columnScope: { All: true },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        handler: ({ value }) => Helper_1.default.isInputNotNullOrEmpty(value),
    },
    // Numeric System Filters
    {
        id: 'GreaterThan',
        label: 'Greater Than',
        icon: { name: 'greater-than' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }],
        handler: ({ value, inputs }) => Number(value) > Number(inputs[0]),
        toString: ({ inputs }) => `> ${inputs[0]}`,
        shortcuts: ['>'],
    },
    {
        id: 'LessThan',
        label: 'Less Than',
        icon: { name: 'less-than' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }],
        handler: ({ value, inputs }) => Number(value) < Number(inputs[0]),
        toString: ({ inputs }) => `< ${inputs[0]}`,
        shortcuts: ['<'],
    },
    {
        id: 'Positive',
        label: 'Positive',
        icon: { text: '>0' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        handler: ({ value }) => Number(value) > 0,
    },
    {
        id: 'Negative',
        label: 'Negative',
        icon: { text: '<0' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        handler: ({ value }) => Number(value) < 0,
    },
    {
        id: 'Zero',
        label: 'Zero',
        icon: { text: '=0' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        handler: ({ value }) => {
            if (typeof value === 'string' && !StringExtensions_1.default.IsNumeric(value)) {
                return false;
            }
            if (Helper_1.default.objectNotExists(value)) {
                return false;
            }
            return Number(value) === 0;
        },
    },
    {
        id: 'Equals',
        label: 'Equals',
        icon: { name: 'equals' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }],
        handler: ({ value, inputs }) => {
            const input = inputs[0];
            if ((typeof value === 'string' && !StringExtensions_1.default.IsNumeric(value)) ||
                (typeof input === 'string' && !StringExtensions_1.default.IsNumeric(input))) {
                return false;
            }
            return Number(value) === Number(inputs[0]);
        },
        toString: ({ inputs }) => `= ${inputs[0]}`,
        shortcuts: ['='],
    },
    {
        id: 'NotEquals',
        label: 'Not Equals',
        icon: { name: 'not-equal' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }],
        handler: ({ value, inputs }) => {
            const input = inputs[0];
            if ((typeof value === 'string' && !StringExtensions_1.default.IsNumeric(value)) ||
                (typeof input === 'string' && !StringExtensions_1.default.IsNumeric(input))) {
                return false;
            }
            return Number(value) !== Number(inputs[0]);
        },
        toString: ({ inputs }) => `!= ${inputs[0]}`,
        shortcuts: ['!='],
    },
    {
        id: 'Between',
        label: 'Between',
        icon: { text: 'BE' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }, { type: 'number' }],
        handler: ({ value, inputs }) => Number(value) >= Number(inputs[0]) && Number(value) <= Number(inputs[1]),
        toString: ({ inputs }) => `Between ${inputs[0]}:${inputs[1]}`,
        shortcuts: [':'],
    },
    {
        id: 'NotBetween',
        label: 'Not Between',
        icon: { text: '!BE' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'number' }, { type: 'number' }],
        handler: ({ value, inputs }) => Number(value) < Number(inputs[0]) || Number(value) > Number(inputs[1]),
        toString: ({ inputs }) => `Not Between ${inputs[0]}:${inputs[1]}`,
        shortcuts: ['!:'],
    },
    {
        id: 'IsNumeric',
        label: 'Is Numeric',
        icon: { text: '1' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['alert', 'flashingcell'],
        handler: ({ value }) => !isNaN(Number(value)),
    },
    {
        id: 'IsNotNumeric',
        label: 'Is Not Numeric',
        icon: { text: '1' },
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['alert', 'flashingcell'],
        handler: ({ value }) => isNaN(Number(value)),
    },
    // String System Filters
    {
        id: 'Is',
        label: 'Equals',
        icon: { name: 'equals' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return false;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v == i;
        },
        toString: ({ inputs }) => `= ${inputs[0]}`,
        shortcuts: ['='],
    },
    {
        id: 'IsNot',
        label: 'Not Equals',
        icon: { name: 'not-equal' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return true;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v != i;
        },
        toString: ({ inputs }) => `!= ${inputs[0]}`,
        shortcuts: ['!='],
    },
    {
        id: 'Contains',
        label: 'Contains',
        icon: { name: 'contains' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return false;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v.indexOf(i) !== -1;
        },
        toString: ({ inputs }) => `Contains ${inputs[0]}`,
    },
    {
        id: 'NotContains',
        label: 'Not Contains',
        icon: { name: 'not-contains' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return true;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v.indexOf(i) === -1;
        },
        toString: ({ inputs }) => `Not Contains ${inputs[0]}`,
    },
    {
        id: 'StartsWith',
        label: 'Starts With',
        icon: { name: 'starts-with' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return false;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v.startsWith(i);
        },
        toString: ({ inputs }) => `Starts With ${inputs[0]}`,
    },
    {
        id: 'EndsWith',
        label: 'Ends With',
        icon: { name: 'ends-with' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs, adaptableApi }) => {
            if (!value) {
                return false;
            }
            const ignoreCase = !adaptableApi.predicateApi.useCaseSensitivity();
            const v = ignoreCase ? String(value).toLocaleLowerCase() : String(value);
            const i = ignoreCase ? String(inputs[0]).toLocaleLowerCase() : String(inputs[0]);
            return v.endsWith(i);
        },
        toString: ({ inputs }) => `Ends With ${inputs[0]}`,
    },
    {
        id: 'Regex',
        label: 'Regex',
        icon: { name: 'regex' },
        columnScope: { DataTypes: ['String'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn', 'badgeStyle'],
        inputs: [{ type: 'text' }],
        handler: ({ value, inputs }) => new RegExp(inputs[0]).test(value),
        toString: ({ inputs }) => `Regex ${inputs[0]}`,
    },
    // Date System Filters
    {
        id: 'Today',
        label: 'Today',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isToday_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'Yesterday',
        label: 'Yesterday',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isYesterday_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'Tomorrow',
        label: 'Tomorrow',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isTomorrow_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'ThisWeek',
        label: 'This Week',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isThisWeek_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'ThisMonth',
        label: 'This Month',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isThisMonth_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'ThisQuarter',
        label: 'This Quarter',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isThisQuarter_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'ThisYear',
        label: 'This Year',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isThisYear_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'InPast',
        label: 'In Past',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isPast_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'InFuture',
        label: 'In Future',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => (0, isFuture_1.default)((0, DateHelper_1.parseDateValue)(value)),
    },
    {
        id: 'After',
        label: 'After',
        icon: { name: 'greater-than' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        inputs: [{ type: 'date' }],
        handler: ({ value, inputs }) => (0, isAfter_1.default)((0, DateHelper_1.parseDateValue)(value), (0, DateHelper_1.parseDateValue)(inputs[0])),
        toString: ({ inputs }) => `> ${inputs[0]}`,
    },
    {
        id: 'Before',
        label: 'Before',
        icon: { name: 'less-than' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        inputs: [{ type: 'date' }],
        handler: ({ value, inputs }) => (0, isBefore_1.default)((0, DateHelper_1.parseDateValue)(value), (0, DateHelper_1.parseDateValue)(inputs[0])),
        toString: ({ inputs }) => `< ${inputs[0]}`,
    },
    {
        id: 'On',
        label: 'Equals',
        icon: { name: 'equals' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        inputs: [{ type: 'date' }],
        handler: ({ value, inputs }) => (0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(value), (0, DateHelper_1.parseDateValue)(inputs[0])),
        toString: ({ inputs }) => `= ${inputs[0]}`,
    },
    {
        id: 'NotOn',
        label: 'NotEquals',
        icon: { name: 'not-equal' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        inputs: [{ type: 'date' }],
        handler: ({ value, inputs }) => !(0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(value), (0, DateHelper_1.parseDateValue)(inputs[0])),
        toString: ({ inputs }) => `!= ${inputs[0]}`,
    },
    {
        id: 'NextWorkDay',
        label: 'Next Work Day',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value, adaptableApi }) => (0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(value), adaptableApi.calendarApi.getNextWorkingDay()),
    },
    {
        id: 'LastWorkDay',
        label: 'Last Work Day',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value, adaptableApi }) => (0, isSameDay_1.default)((0, DateHelper_1.parseDateValue)(value), adaptableApi.calendarApi.getPreviousWorkingDay()),
    },
    {
        id: 'WorkDay',
        label: 'Working Day',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value, adaptableApi }) => adaptableApi.calendarApi.isWorkingDay(value),
    },
    {
        id: 'Holiday',
        label: 'Holiday',
        icon: { name: 'calendar' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value, adaptableApi }) => adaptableApi.calendarApi.isHoliday(value),
    },
    {
        id: 'InRange',
        label: 'Range',
        icon: { name: 'date-range' },
        columnScope: { DataTypes: ['Date'] },
        moduleScope: ['columnFilter'],
        inputs: [{ type: 'date' }, { type: 'date' }],
        handler: ({ value, inputs }) => new Date(value) >= new Date(inputs[0]) && new Date(value) <= new Date(inputs[1]),
    },
    // Boolean System Filters
    {
        id: 'True',
        label: 'True',
        icon: { text: 'T' },
        columnScope: { DataTypes: ['Boolean'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => Boolean(value) === true,
    },
    {
        id: 'False',
        label: 'False',
        icon: { text: 'F' },
        columnScope: { DataTypes: ['Boolean'] },
        moduleScope: ['columnFilter', 'alert', 'flashingcell', 'formatColumn'],
        handler: ({ value }) => Boolean(value) === false,
    },
    {
        id: 'BooleanToggle',
        label: 'BooleanToggle',
        icon: { name: 'boolean-list' },
        columnScope: { DataTypes: ['Boolean'] },
        moduleScope: ['columnFilter'],
        inputs: [{ type: 'boolean' }],
        // working with string aliases instead of booleans because the ColumnFilterAPI cannot handle falsy filter values (it ignores them)
        handler: ({ value, inputs }) => {
            if (inputs[0] == 'all') {
                // if it's indeterminate, all values (true&false) are matched
                return true;
            }
            const booleanInputValue = inputs[0] === 'checked' ? true : false;
            return Boolean(value) === Boolean(booleanInputValue);
        },
    },
    // Other System Filters
    {
        id: 'AnyChange',
        label: 'Any Change',
        columnScope: { All: true },
        moduleScope: ['alert', 'flashingcell'],
        handler: ({ value, oldValue }) => value !== oldValue,
    },
    {
        id: 'PercentChange',
        label: 'Percent Change',
        columnScope: { DataTypes: ['Number'] },
        moduleScope: ['alert', 'flashingcell'],
        inputs: [{ type: 'number' }],
        handler: ({ value, oldValue, inputs }) => {
            const change = Math.abs(Number(value) - Number(oldValue));
            const base = Math.min(Number(value), Number(oldValue));
            const threshold = Number(inputs[0]);
            return (change / base) * 100 > threshold;
        },
    },
    {
        id: 'ExistingValuesOnly',
        label: 'Existing Values Only',
        columnScope: { All: true },
        moduleScope: ['alert'],
        handler: ({ value, adaptableApi, column, node }) => {
            const distinctValues = column
                ? adaptableApi.gridApi.internalApi.getDistinctRawValuesForColumn(column.columnId, node)
                : [];
            return !distinctValues.includes(value);
        },
    },
    {
        id: 'NoDuplicateValues',
        label: 'No Duplicate Values',
        columnScope: { All: true },
        moduleScope: ['alert'],
        handler: ({ value, adaptableApi, column, node }) => {
            const distinctValues = column
                ? adaptableApi.gridApi.internalApi.getDistinctRawValuesForColumn(column.columnId, node)
                : [];
            return distinctValues.includes(value);
        },
    },
    {
        id: 'AddedRow',
        label: 'Added Row(s)',
        columnScope: { All: true },
        moduleScope: ['alert'],
        handler: () => {
            // handled in AlertModule as an eventHandler
            return false;
        },
    },
    {
        id: 'RemovedRow',
        label: 'Removed Row(s)',
        columnScope: { All: true },
        moduleScope: ['alert'],
        handler: () => {
            // handled in AlertModule as an eventHandler
            return false;
        },
    },
];
exports.SystemFilterPredicateIds = exports.SystemPredicateDefs.filter((p) => p.moduleScope.includes('columnFilter')).map((p) => p.id);
exports.SystemAlertPredicateIds = exports.SystemPredicateDefs.filter((p) => p.moduleScope.includes('alert')).map((p) => p.id);
exports.SystemFormatColumnPredicateIds = exports.SystemPredicateDefs.filter((p) => p.moduleScope.includes('formatColumn')).map((p) => p.id);
exports.SystemFlashingCellPredicateIds = exports.SystemPredicateDefs.filter((p) => p.moduleScope.includes('flashingcell')).map((p) => p.id);
exports.SystemBadgeStylePredicateIds = exports.SystemPredicateDefs.filter((p) => p.moduleScope.includes('badgeStyle')).map((p) => p.id);
