src/automata@event@filter.erl

-module(automata@event@filter).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/automata/event/filter.gleam").
-export([always/0, never/0, predicate/1, by_source/1, by_source_kind/1, by_source_id/1, by_correlation_id/1, by_causation_id/1, by_trace_id/1, by_attribute/2, has_attribute/1, occurred_between/2, occurred_after/1, occurred_before/1, on_body/1, on_body_option/2, all_of/1, any_of/1, negate/1, matches/2, keep/2, reject/2]).
-export_type([filter/1]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

-opaque filter(ERJ) :: {filter, fun((automata@event:event(ERJ)) -> boolean())}.

-file("src/automata/event/filter.gleam", 22).
?DOC(
    " A filter that accepts every event. Useful as the identity element\n"
    " for `all_of` (the empty list of filters reduces to `always`).\n"
).
-spec always() -> filter(any()).
always() ->
    {filter, fun(_) -> true end}.

-file("src/automata/event/filter.gleam", 28).
?DOC(
    " A filter that rejects every event. Useful as the identity element\n"
    " for `any_of` (the empty list of filters reduces to `never`).\n"
).
-spec never() -> filter(any()).
never() ->
    {filter, fun(_) -> false end}.

-file("src/automata/event/filter.gleam", 36).
?DOC(
    " Build a filter from an arbitrary predicate.\n"
    "\n"
    " The escape hatch for conditions that the built-in constructors do\n"
    " not express. Prefer the typed constructors below when one fits.\n"
).
-spec predicate(fun((automata@event:event(ERO)) -> boolean())) -> filter(ERO).
predicate(Check) ->
    {filter, Check}.

-file("src/automata/event/filter.gleam", 40).
-spec by_source(automata@event@source:source()) -> filter(any()).
by_source(Source) ->
    {filter, fun(Event) -> erlang:element(4, Event) =:= Source end}.

-file("src/automata/event/filter.gleam", 44).
-spec by_source_kind(automata@event@source:source_kind()) -> filter(any()).
by_source_kind(Kind) ->
    {filter,
        fun(Event) -> erlang:element(2, erlang:element(4, Event)) =:= Kind end}.

-file("src/automata/event/filter.gleam", 48).
-spec by_source_id(binary()) -> filter(any()).
by_source_id(Id) ->
    {filter,
        fun(Event) -> erlang:element(3, erlang:element(4, Event)) =:= Id end}.

-file("src/automata/event/filter.gleam", 52).
-spec by_correlation_id(binary()) -> filter(any()).
by_correlation_id(Id) ->
    {filter,
        fun(Event) ->
            erlang:element(2, erlang:element(6, Event)) =:= {some, Id}
        end}.

-file("src/automata/event/filter.gleam", 56).
-spec by_causation_id(binary()) -> filter(any()).
by_causation_id(Id) ->
    {filter,
        fun(Event) ->
            erlang:element(3, erlang:element(6, Event)) =:= {some, Id}
        end}.

-file("src/automata/event/filter.gleam", 60).
-spec by_trace_id(binary()) -> filter(any()).
by_trace_id(Id) ->
    {filter,
        fun(Event) ->
            erlang:element(4, erlang:element(6, Event)) =:= {some, Id}
        end}.

-file("src/automata/event/filter.gleam", 64).
-spec by_attribute(binary(), binary()) -> filter(any()).
by_attribute(Key, Value) ->
    {filter,
        fun(Event) ->
            automata@event@metadata:attribute(erlang:element(6, Event), Key) =:= {some,
                Value}
        end}.

-file("src/automata/event/filter.gleam", 70).
-spec has_attribute(binary()) -> filter(any()).
has_attribute(Key) ->
    {filter,
        fun(Event) ->
            automata@event@metadata:has_attribute(erlang:element(6, Event), Key)
        end}.

-file("src/automata/event/filter.gleam", 77).
?DOC(" Match events whose `occurred_at` falls in `[from, until]` (inclusive).\n").
-spec occurred_between(
    automata@schedule@ast:valid_date_time(),
    automata@schedule@ast:valid_date_time()
) -> filter(any()).
occurred_between(From, Until) ->
    From_raw = automata@schedule@ast:valid_datetime_value(From),
    Until_raw = automata@schedule@ast:valid_datetime_value(Until),
    {filter,
        fun(Event) ->
            Occurred = automata@schedule@ast:valid_datetime_value(
                erlang:element(3, Event)
            ),
            automata@internal@calendar:greater_or_equal(Occurred, From_raw)
            andalso automata@internal@calendar:less_or_equal(
                Occurred,
                Until_raw
            )
        end}.

-file("src/automata/event/filter.gleam", 90).
-spec occurred_after(automata@schedule@ast:valid_date_time()) -> filter(any()).
occurred_after(After) ->
    After_raw = automata@schedule@ast:valid_datetime_value(After),
    {filter,
        fun(Event) ->
            automata@internal@calendar:greater_than(
                automata@schedule@ast:valid_datetime_value(
                    erlang:element(3, Event)
                ),
                After_raw
            )
        end}.

-file("src/automata/event/filter.gleam", 100).
-spec occurred_before(automata@schedule@ast:valid_date_time()) -> filter(any()).
occurred_before(Before) ->
    Before_raw = automata@schedule@ast:valid_datetime_value(Before),
    {filter,
        fun(Event) ->
            automata@internal@calendar:less_than(
                automata@schedule@ast:valid_datetime_value(
                    erlang:element(3, Event)
                ),
                Before_raw
            )
        end}.

-file("src/automata/event/filter.gleam", 145).
?DOC(
    " Lift a body-only predicate into a `Filter(body)`. Useful for\n"
    " constructing body-shape filters in `automata/event/builtin/filter`.\n"
).
-spec on_body(fun((ETN) -> boolean())) -> filter(ETN).
on_body(Check) ->
    {filter, fun(Event) -> Check(erlang:element(5, Event)) end}.

-file("src/automata/event/filter.gleam", 153).
?DOC(
    " Lift a body-to-`Option(value)` extractor and a value predicate.\n"
    "\n"
    " Returns `False` when the extractor yields `None`. Used by builtin\n"
    " filters that target a specific variant (e.g. `FileModified.path`).\n"
).
-spec on_body_option(
    fun((ETP) -> gleam@option:option(ETQ)),
    fun((ETQ) -> boolean())
) -> filter(ETP).
on_body_option(Extract, Check) ->
    {filter, fun(Event) -> case Extract(erlang:element(5, Event)) of
                {some, Value} ->
                    Check(Value);

                none ->
                    false
            end end}.

-file("src/automata/event/filter.gleam", 165).
-spec run(filter(ETT), automata@event:event(ETT)) -> boolean().
run(Filter, Event) ->
    (erlang:element(2, Filter))(Event).

-file("src/automata/event/filter.gleam", 111).
?DOC(" Logical AND across all filters. An empty list is `always`.\n").
-spec all_of(list(filter(ESN))) -> filter(ESN).
all_of(Filters) ->
    {filter,
        fun(Event) ->
            gleam@list:all(Filters, fun(Filter) -> run(Filter, Event) end)
        end}.

-file("src/automata/event/filter.gleam", 116).
?DOC(" Logical OR across all filters. An empty list is `never`.\n").
-spec any_of(list(filter(ESR))) -> filter(ESR).
any_of(Filters) ->
    {filter,
        fun(Event) ->
            gleam@list:any(Filters, fun(Filter) -> run(Filter, Event) end)
        end}.

-file("src/automata/event/filter.gleam", 121).
?DOC(" Logical negation. Named `negate` because `not` is a reserved word.\n").
-spec negate(filter(ESV)) -> filter(ESV).
negate(Filter) ->
    {filter, fun(Event) -> not run(Filter, Event) end}.

-file("src/automata/event/filter.gleam", 125).
-spec matches(filter(ESY), automata@event:event(ESY)) -> boolean().
matches(Filter, Event) ->
    run(Filter, Event).

-file("src/automata/event/filter.gleam", 129).
-spec keep(filter(ETB), list(automata@event:event(ETB))) -> list(automata@event:event(ETB)).
keep(Filter, Events) ->
    gleam@list:filter(Events, fun(Event) -> run(Filter, Event) end).

-file("src/automata/event/filter.gleam", 136).
-spec reject(filter(ETH), list(automata@event:event(ETH))) -> list(automata@event:event(ETH)).
reject(Filter, Events) ->
    gleam@list:filter(Events, fun(Event) -> not run(Filter, Event) end).