import Input, { InputType } from "../Input/Input";
import FieldType from "../Types/FieldType";
import FilterOperator from "./Types/FilterOperator";
import OperatorSelector from "./OperatorSelector";
import InBetween from "../../../Types/BaseDatabase/InBetween";
import GreaterThan from "../../../Types/BaseDatabase/GreaterThan";
import LessThan from "../../../Types/BaseDatabase/LessThan";
import EqualTo from "../../../Types/BaseDatabase/EqualTo";
import IsNull from "../../../Types/BaseDatabase/IsNull";
import NotNull from "../../../Types/BaseDatabase/NotNull";
import OneUptimeDate from "../../../Types/Date";
import React, { useEffect, useState } from "react";
const DATE_OPERATORS = [
    FilterOperator.Is,
    FilterOperator.Before,
    FilterOperator.After,
    FilterOperator.Between,
    FilterOperator.IsEmpty,
    FilterOperator.IsNotEmpty,
];
const toDate = (value) => {
    if (!value) {
        return null;
    }
    if (value instanceof Date) {
        return value;
    }
    try {
        return OneUptimeDate.fromString(value);
    }
    catch (_a) {
        return null;
    }
};
const detectState = (rawValue) => {
    if (rawValue instanceof InBetween) {
        const start = toDate(rawValue.startValue);
        const end = toDate(rawValue.endValue);
        // If start/end match the bounds of a single day, treat as "Is".
        if (start && end) {
            const startOfDay = OneUptimeDate.getStartOfDay(start);
            const endOfDay = OneUptimeDate.getEndOfDay(start);
            if (start.getTime() === startOfDay.getTime() &&
                end.getTime() === endOfDay.getTime()) {
                return { operator: FilterOperator.Is, start, end: null };
            }
        }
        return { operator: FilterOperator.Between, start, end };
    }
    if (rawValue instanceof GreaterThan) {
        return {
            operator: FilterOperator.After,
            start: toDate(rawValue.value),
            end: null,
        };
    }
    if (rawValue instanceof LessThan) {
        return {
            operator: FilterOperator.Before,
            start: toDate(rawValue.value),
            end: null,
        };
    }
    if (rawValue instanceof EqualTo) {
        return {
            operator: FilterOperator.Is,
            start: toDate(rawValue.value),
            end: null,
        };
    }
    if (rawValue instanceof IsNull) {
        return { operator: FilterOperator.IsEmpty, start: null, end: null };
    }
    if (rawValue instanceof NotNull) {
        return { operator: FilterOperator.IsNotEmpty, start: null, end: null };
    }
    return { operator: FilterOperator.Is, start: null, end: null };
};
const buildValue = (state, isDateTime) => {
    switch (state.operator) {
        case FilterOperator.Is: {
            if (!state.start) {
                return undefined;
            }
            if (isDateTime) {
                return new EqualTo(state.start);
            }
            return new InBetween(OneUptimeDate.getStartOfDay(state.start), OneUptimeDate.getEndOfDay(state.start));
        }
        case FilterOperator.Before:
            return state.start ? new LessThan(state.start) : undefined;
        case FilterOperator.After:
            return state.start ? new GreaterThan(state.start) : undefined;
        case FilterOperator.Between: {
            if (!state.start || !state.end) {
                return undefined;
            }
            return new InBetween((isDateTime
                ? state.start
                : OneUptimeDate.getStartOfDay(state.start)), (isDateTime ? state.end : OneUptimeDate.getEndOfDay(state.end)));
        }
        case FilterOperator.IsEmpty:
            return new IsNull();
        case FilterOperator.IsNotEmpty:
            return new NotNull();
        default:
            return undefined;
    }
};
const DateFilter = (props) => {
    const filter = props.filter;
    if (filter.type !== FieldType.Date && filter.type !== FieldType.DateTime) {
        return React.createElement(React.Fragment, null);
    }
    const isDateTime = filter.type === FieldType.DateTime;
    const detected = detectState(props.filterData[filter.key]);
    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 state = Object.assign(Object.assign({}, detected), { operator: localOperator });
    const valuelessOperator = state.operator === FilterOperator.IsEmpty ||
        state.operator === FilterOperator.IsNotEmpty;
    const isBetween = state.operator === FilterOperator.Between;
    const apply = (nextState) => {
        var _a;
        if (!filter.key) {
            return;
        }
        setLocalOperator(nextState.operator);
        const next = Object.assign({}, props.filterData);
        const built = buildValue(nextState, isDateTime);
        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);
    };
    const inputType = isDateTime
        ? InputType.DATETIME_LOCAL
        : InputType.DATE;
    return (React.createElement("div", { className: "flex gap-2 items-start" },
        React.createElement(OperatorSelector, { value: state.operator, options: DATE_OPERATORS, onChange: (nextOperator) => {
                apply(Object.assign(Object.assign({}, state), { operator: nextOperator }));
            } }),
        !valuelessOperator && (React.createElement("div", { className: isBetween ? "flex-1 flex gap-2 min-w-0" : "flex-1 min-w-0" },
            React.createElement("div", { className: "flex-1 min-w-0" },
                React.createElement(Input, { key: `${filter.key}-start-${state.operator}`, onChange: (changed) => {
                        const parsed = toDate(changed);
                        apply(Object.assign(Object.assign({}, state), { start: parsed }));
                    }, value: state.start || "", placeholder: isBetween ? "From" : `Filter by ${filter.title}`, type: inputType, outerDivClassName: "relative rounded-md w-full" })),
            isBetween && (React.createElement("div", { className: "flex-1 min-w-0" },
                React.createElement(Input, { key: `${filter.key}-end-${state.operator}`, onChange: (changed) => {
                        const parsed = toDate(changed);
                        apply(Object.assign(Object.assign({}, state), { end: parsed }));
                    }, value: state.end || "", placeholder: "To", type: inputType, outerDivClassName: "relative rounded-md w-full" })))))));
};
export default DateFilter;
//# sourceMappingURL=DateFilter.js.map