import EqualTo from "../../../Types/BaseDatabase/EqualTo";
import NotEqual from "../../../Types/BaseDatabase/NotEqual";
import Search from "../../../Types/BaseDatabase/Search";
import NotContains from "../../../Types/BaseDatabase/NotContains";
import StartsWith from "../../../Types/BaseDatabase/StartsWith";
import EndsWith from "../../../Types/BaseDatabase/EndsWith";
import GreaterThan from "../../../Types/BaseDatabase/GreaterThan";
import GreaterThanOrEqual from "../../../Types/BaseDatabase/GreaterThanOrEqual";
import LessThan from "../../../Types/BaseDatabase/LessThan";
import LessThanOrEqual from "../../../Types/BaseDatabase/LessThanOrEqual";
import IsNull from "../../../Types/BaseDatabase/IsNull";
import NotNull from "../../../Types/BaseDatabase/NotNull";
import { ObjectType } from "../../../Types/JSON";
/*
 * UI-facing operator identifiers. We store these in the Dictionary form
 * state and translate to the corresponding backend operator wrapper at
 * the API boundary so the existing serialization pipeline works.
 */
export var DictionaryFilterOperator;
(function (DictionaryFilterOperator) {
    DictionaryFilterOperator["EqualTo"] = "EqualTo";
    DictionaryFilterOperator["NotEqual"] = "NotEqual";
    DictionaryFilterOperator["Contains"] = "Contains";
    DictionaryFilterOperator["NotContains"] = "NotContains";
    DictionaryFilterOperator["StartsWith"] = "StartsWith";
    DictionaryFilterOperator["EndsWith"] = "EndsWith";
    DictionaryFilterOperator["GreaterThan"] = "GreaterThan";
    DictionaryFilterOperator["LessThan"] = "LessThan";
    DictionaryFilterOperator["GreaterThanOrEqual"] = "GreaterThanOrEqual";
    DictionaryFilterOperator["LessThanOrEqual"] = "LessThanOrEqual";
    DictionaryFilterOperator["IsEmpty"] = "IsEmpty";
    DictionaryFilterOperator["IsNotEmpty"] = "IsNotEmpty";
})(DictionaryFilterOperator || (DictionaryFilterOperator = {}));
export const DICTIONARY_FILTER_OPERATOR_OPTIONS = [
    {
        operator: DictionaryFilterOperator.EqualTo,
        label: "equals",
        symbol: "=",
    },
    {
        operator: DictionaryFilterOperator.NotEqual,
        label: "does not equal",
        symbol: "!=",
    },
    {
        operator: DictionaryFilterOperator.Contains,
        label: "contains",
        symbol: "contains",
    },
    {
        operator: DictionaryFilterOperator.NotContains,
        label: "does not contain",
        symbol: "does not contain",
    },
    {
        operator: DictionaryFilterOperator.StartsWith,
        label: "starts with",
        symbol: "starts with",
    },
    {
        operator: DictionaryFilterOperator.EndsWith,
        label: "ends with",
        symbol: "ends with",
    },
    {
        operator: DictionaryFilterOperator.GreaterThan,
        label: "greater than",
        symbol: ">",
        expectsNumericValue: true,
    },
    {
        operator: DictionaryFilterOperator.GreaterThanOrEqual,
        label: "greater than or equal",
        symbol: ">=",
        expectsNumericValue: true,
    },
    {
        operator: DictionaryFilterOperator.LessThan,
        label: "less than",
        symbol: "<",
        expectsNumericValue: true,
    },
    {
        operator: DictionaryFilterOperator.LessThanOrEqual,
        label: "less than or equal",
        symbol: "<=",
        expectsNumericValue: true,
    },
    {
        operator: DictionaryFilterOperator.IsEmpty,
        label: "is empty",
        symbol: "is empty",
        hidesValueInput: true,
    },
    {
        operator: DictionaryFilterOperator.IsNotEmpty,
        label: "is not empty",
        symbol: "is not empty",
        hidesValueInput: true,
    },
];
export const getOperatorOption = (operator) => {
    var _a;
    return ((_a = DICTIONARY_FILTER_OPERATOR_OPTIONS.find((option) => {
        return option.operator === operator;
    })) !== null && _a !== void 0 ? _a : DICTIONARY_FILTER_OPERATOR_OPTIONS[0]);
};
const matchesObjectType = (value, type) => {
    return Boolean(value &&
        typeof value === "object" &&
        value._type === type);
};
/**
 * Inspect a stored dictionary entry value (which may be a plain string,
 * a hydrated operator instance, or a raw `{_type, value}` JSON shape)
 * and recover the operator + display value used to populate the form.
 */
export const detectOperatorFromValue = (value) => {
    if (value === null || value === undefined) {
        return {
            operator: DictionaryFilterOperator.EqualTo,
            rawValue: "",
        };
    }
    if (typeof value === "string" ||
        typeof value === "number" ||
        typeof value === "boolean") {
        return {
            operator: DictionaryFilterOperator.EqualTo,
            rawValue: String(value),
        };
    }
    if (value instanceof IsNull || matchesObjectType(value, ObjectType.IsNull)) {
        return { operator: DictionaryFilterOperator.IsEmpty, rawValue: "" };
    }
    if (value instanceof NotNull ||
        matchesObjectType(value, ObjectType.NotNull)) {
        return { operator: DictionaryFilterOperator.IsNotEmpty, rawValue: "" };
    }
    const wrapperValue = value instanceof Object && "value" in value
        ? String(value.value === undefined ||
            value.value === null
            ? ""
            : value.value)
        : "";
    if (value instanceof NotEqual ||
        matchesObjectType(value, ObjectType.NotEqual)) {
        return {
            operator: DictionaryFilterOperator.NotEqual,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof EqualTo ||
        matchesObjectType(value, ObjectType.EqualTo)) {
        return {
            operator: DictionaryFilterOperator.EqualTo,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof Search || matchesObjectType(value, ObjectType.Search)) {
        return {
            operator: DictionaryFilterOperator.Contains,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof NotContains ||
        matchesObjectType(value, ObjectType.NotContains)) {
        return {
            operator: DictionaryFilterOperator.NotContains,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof StartsWith ||
        matchesObjectType(value, ObjectType.StartsWith)) {
        return {
            operator: DictionaryFilterOperator.StartsWith,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof EndsWith ||
        matchesObjectType(value, ObjectType.EndsWith)) {
        return {
            operator: DictionaryFilterOperator.EndsWith,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof GreaterThan ||
        matchesObjectType(value, ObjectType.GreaterThan)) {
        return {
            operator: DictionaryFilterOperator.GreaterThan,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof GreaterThanOrEqual ||
        matchesObjectType(value, ObjectType.GreaterThanOrEqual)) {
        return {
            operator: DictionaryFilterOperator.GreaterThanOrEqual,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof LessThan ||
        matchesObjectType(value, ObjectType.LessThan)) {
        return {
            operator: DictionaryFilterOperator.LessThan,
            rawValue: wrapperValue,
        };
    }
    if (value instanceof LessThanOrEqual ||
        matchesObjectType(value, ObjectType.LessThanOrEqual)) {
        return {
            operator: DictionaryFilterOperator.LessThanOrEqual,
            rawValue: wrapperValue,
        };
    }
    // Unknown structure — fall back to bare equality with stringified value.
    return {
        operator: DictionaryFilterOperator.EqualTo,
        rawValue: wrapperValue,
    };
};
/**
 * Build the actual stored dictionary value for an operator + raw value.
 * `EqualTo` produces a bare string for backwards compatibility with
 * existing saved filters; everything else produces an operator wrapper
 * instance.
 */
export const buildDictionaryValue = (input) => {
    const { operator, rawValue } = input;
    const trimmed = rawValue !== null && rawValue !== void 0 ? rawValue : "";
    switch (operator) {
        case DictionaryFilterOperator.EqualTo:
            return trimmed;
        case DictionaryFilterOperator.NotEqual:
            return new NotEqual(trimmed);
        case DictionaryFilterOperator.Contains:
            /*
             * Statement.serialize already wraps Search instances with `%...%`,
             * so pass the bare needle here.
             */
            return new Search(trimmed);
        case DictionaryFilterOperator.NotContains:
            return new NotContains(trimmed);
        case DictionaryFilterOperator.StartsWith:
            return new StartsWith(trimmed);
        case DictionaryFilterOperator.EndsWith:
            return new EndsWith(trimmed);
        case DictionaryFilterOperator.GreaterThan:
            return new GreaterThan(Number(trimmed));
        case DictionaryFilterOperator.GreaterThanOrEqual:
            return new GreaterThanOrEqual(Number(trimmed));
        case DictionaryFilterOperator.LessThan:
            return new LessThan(Number(trimmed));
        case DictionaryFilterOperator.LessThanOrEqual:
            return new LessThanOrEqual(Number(trimmed));
        case DictionaryFilterOperator.IsEmpty:
            return new IsNull();
        case DictionaryFilterOperator.IsNotEmpty:
            return new NotNull();
        default:
            return trimmed;
    }
};
//# sourceMappingURL=DictionaryFilterOperator.js.map