import FieldType from "../Types/FieldType";
import FilterOperator from "./Types/FilterOperator";
import OperatorSelector from "./OperatorSelector";
import Search from "../../../Types/BaseDatabase/Search";
import EqualTo from "../../../Types/BaseDatabase/EqualTo";
import NotEqual from "../../../Types/BaseDatabase/NotEqual";
import StartsWith from "../../../Types/BaseDatabase/StartsWith";
import EndsWith from "../../../Types/BaseDatabase/EndsWith";
import NotContains from "../../../Types/BaseDatabase/NotContains";
import IsNull from "../../../Types/BaseDatabase/IsNull";
import NotNull from "../../../Types/BaseDatabase/NotNull";
import React, { useEffect, useState } from "react";
const TEXT_FIELD_TYPES = [
    FieldType.Text,
    FieldType.LongText,
    FieldType.Email,
    FieldType.Phone,
    FieldType.Name,
    FieldType.Port,
    FieldType.URL,
    FieldType.Hostname,
    FieldType.ObjectID,
];
const TEXT_OPERATORS = [
    FilterOperator.Contains,
    FilterOperator.DoesNotContain,
    FilterOperator.EqualTo,
    FilterOperator.NotEqualTo,
    FilterOperator.StartsWith,
    FilterOperator.EndsWith,
    FilterOperator.IsEmpty,
    FilterOperator.IsNotEmpty,
];
const detectCurrentState = (rawValue) => {
    if (rawValue instanceof Search) {
        return { operator: FilterOperator.Contains, value: rawValue.value };
    }
    if (rawValue instanceof NotContains) {
        return { operator: FilterOperator.DoesNotContain, value: rawValue.value };
    }
    if (rawValue instanceof StartsWith) {
        return { operator: FilterOperator.StartsWith, value: rawValue.value };
    }
    if (rawValue instanceof EndsWith) {
        return { operator: FilterOperator.EndsWith, value: rawValue.value };
    }
    if (rawValue instanceof EqualTo) {
        return { operator: FilterOperator.EqualTo, value: rawValue.toString() };
    }
    if (rawValue instanceof NotEqual) {
        return { operator: FilterOperator.NotEqualTo, value: rawValue.toString() };
    }
    if (rawValue instanceof IsNull) {
        return { operator: FilterOperator.IsEmpty, value: "" };
    }
    if (rawValue instanceof NotNull) {
        return { operator: FilterOperator.IsNotEmpty, value: "" };
    }
    if (typeof rawValue === "string" && rawValue.length > 0) {
        // Backward compatibility for plain string values.
        return { operator: FilterOperator.Contains, value: rawValue };
    }
    return { operator: FilterOperator.Contains, value: "" };
};
const buildQueryValue = (operator, value) => {
    switch (operator) {
        case FilterOperator.Contains:
            return value ? new Search(value) : undefined;
        case FilterOperator.DoesNotContain:
            return value ? new NotContains(value) : undefined;
        case FilterOperator.StartsWith:
            return value ? new StartsWith(value) : undefined;
        case FilterOperator.EndsWith:
            return value ? new EndsWith(value) : undefined;
        case FilterOperator.EqualTo:
            return value ? new EqualTo(value) : undefined;
        case FilterOperator.NotEqualTo:
            return value ? new NotEqual(value) : undefined;
        case FilterOperator.IsEmpty:
            return new IsNull();
        case FilterOperator.IsNotEmpty:
            return new NotNull();
        default:
            return undefined;
    }
};
const TextFilter = (props) => {
    const filter = props.filter;
    if (filter.filterDropdownOptions) {
        return React.createElement(React.Fragment, null);
    }
    if (!TEXT_FIELD_TYPES.includes(filter.type)) {
        return React.createElement(React.Fragment, null);
    }
    const detected = detectCurrentState(props.filterData[filter.key]);
    /*
     * Keep the operator locally so the user's choice persists even when no
     * value has been typed yet (otherwise buildQueryValue returns undefined,
     * the filter is deleted, and the operator resets on re-render).
     */
    const [localOperator, setLocalOperator] = useState(detected.operator);
    useEffect(() => {
        const raw = props.filterData[filter.key];
        if (raw !== undefined && raw !== null) {
            setLocalOperator(detected.operator);
        }
    }, [props.filterData[filter.key]]);
    const operator = localOperator;
    const value = detected.value;
    const valuelessOperator = operator === FilterOperator.IsEmpty ||
        operator === FilterOperator.IsNotEmpty;
    const apply = (data) => {
        var _a;
        if (!filter.key) {
            return;
        }
        setLocalOperator(data.operator);
        const next = Object.assign({}, props.filterData);
        const built = buildQueryValue(data.operator, data.value);
        if (built === undefined) {
            delete next[filter.key];
        }
        else {
            next[filter.key] = built;
        }
        (_a = props.onFilterChanged) === null || _a === void 0 ? void 0 : _a.call(props, next);
    };
    return (React.createElement("div", { className: "flex gap-2 items-start" },
        React.createElement(OperatorSelector, { value: operator, options: TEXT_OPERATORS, onChange: (nextOperator) => {
                apply({ operator: nextOperator, value });
            } }),
        !valuelessOperator && (React.createElement("div", { className: "flex-1 min-w-0" },
            React.createElement("input", { type: "text", value: value, onChange: (e) => {
                    apply({ operator, value: e.target.value });
                }, placeholder: `Filter by ${filter.title}`, className: "block w-full rounded-md border border-gray-300 bg-white py-2 pl-3 pr-3 text-sm placeholder-gray-500 focus:border-indigo-500 focus:text-gray-900 focus:placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm" })))));
};
export default TextFilter;
//# sourceMappingURL=TextFilter.js.map