src/automata@cron@builder.erl

-module(automata@cron@builder).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/automata/cron/builder.gleam").
-export([builder/0, any/0, at/1, between/2, every/1, every_from/2, every_between/3, one_of/1, with_minute/2, with_hour/2, with_day_of_month/2, with_month/2, with_day_of_week/2, build/1]).
-export_type([builder/0]).

-opaque builder() :: {builder,
        automata@cron@validator:selector(),
        automata@cron@validator:selector(),
        automata@cron@validator:selector(),
        automata@cron@validator:selector(),
        automata@cron@validator:selector()}.

-file("src/automata/cron/builder.gleam", 24).
-spec builder() -> builder().
builder() ->
    {builder, any, any, any, any, any}.

-file("src/automata/cron/builder.gleam", 34).
-spec any() -> automata@cron@validator:selector().
any() ->
    any.

-file("src/automata/cron/builder.gleam", 38).
-spec at(integer()) -> automata@cron@validator:selector().
at(Value) ->
    {values, [{exact, Value}]}.

-file("src/automata/cron/builder.gleam", 42).
-spec between(integer(), integer()) -> automata@cron@validator:selector().
between(Start, End) ->
    {values, [{range, Start, End}]}.

-file("src/automata/cron/builder.gleam", 46).
-spec every(integer()) -> automata@cron@validator:selector().
every(Step) ->
    {values, [{step, step_any, Step}]}.

-file("src/automata/cron/builder.gleam", 50).
-spec every_from(integer(), integer()) -> automata@cron@validator:selector().
every_from(Start, Step) ->
    {values, [{step, {step_exact, Start}, Step}]}.

-file("src/automata/cron/builder.gleam", 54).
-spec every_between(integer(), integer(), integer()) -> automata@cron@validator:selector().
every_between(Start, End, Step) ->
    {values, [{step, {step_range, Start, End}, Step}]}.

-file("src/automata/cron/builder.gleam", 62).
-spec one_of(list(automata@cron@validator:item())) -> automata@cron@validator:selector().
one_of(Items) ->
    {values, Items}.

-file("src/automata/cron/builder.gleam", 66).
-spec with_minute(builder(), automata@cron@validator:selector()) -> builder().
with_minute(Builder, Minute) ->
    {builder,
        Minute,
        erlang:element(3, Builder),
        erlang:element(4, Builder),
        erlang:element(5, Builder),
        erlang:element(6, Builder)}.

-file("src/automata/cron/builder.gleam", 70).
-spec with_hour(builder(), automata@cron@validator:selector()) -> builder().
with_hour(Builder, Hour) ->
    {builder,
        erlang:element(2, Builder),
        Hour,
        erlang:element(4, Builder),
        erlang:element(5, Builder),
        erlang:element(6, Builder)}.

-file("src/automata/cron/builder.gleam", 74).
-spec with_day_of_month(builder(), automata@cron@validator:selector()) -> builder().
with_day_of_month(Builder, Day_of_month) ->
    {builder,
        erlang:element(2, Builder),
        erlang:element(3, Builder),
        Day_of_month,
        erlang:element(5, Builder),
        erlang:element(6, Builder)}.

-file("src/automata/cron/builder.gleam", 81).
-spec with_month(builder(), automata@cron@validator:selector()) -> builder().
with_month(Builder, Month) ->
    {builder,
        erlang:element(2, Builder),
        erlang:element(3, Builder),
        erlang:element(4, Builder),
        Month,
        erlang:element(6, Builder)}.

-file("src/automata/cron/builder.gleam", 85).
-spec with_day_of_week(builder(), automata@cron@validator:selector()) -> builder().
with_day_of_week(Builder, Day_of_week) ->
    {builder,
        erlang:element(2, Builder),
        erlang:element(3, Builder),
        erlang:element(4, Builder),
        erlang:element(5, Builder),
        Day_of_week}.

-file("src/automata/cron/builder.gleam", 151).
-spec selector_is_empty(automata@cron@validator:selector()) -> boolean().
selector_is_empty(Selector) ->
    case Selector of
        any ->
            false;

        {values, Items} ->
            Items =:= []
    end.

-file("src/automata/cron/builder.gleam", 128).
-spec first_empty_selector(builder()) -> gleam@option:option(automata@cron@ast:field()).
first_empty_selector(Builder) ->
    case selector_is_empty(erlang:element(2, Builder)) of
        true ->
            {some, minute};

        false ->
            case selector_is_empty(erlang:element(3, Builder)) of
                true ->
                    {some, hour};

                false ->
                    case selector_is_empty(erlang:element(4, Builder)) of
                        true ->
                            {some, day_of_month};

                        false ->
                            case selector_is_empty(erlang:element(5, Builder)) of
                                true ->
                                    {some, month};

                                false ->
                                    case selector_is_empty(
                                        erlang:element(6, Builder)
                                    ) of
                                        true ->
                                            {some, day_of_week};

                                        false ->
                                            none
                                    end
                            end
                    end
            end
    end.

-file("src/automata/cron/builder.gleam", 178).
-spec step_base_to_string(automata@cron@validator:step_base()) -> binary().
step_base_to_string(Base) ->
    case Base of
        step_any ->
            <<"*"/utf8>>;

        {step_exact, Value} ->
            erlang:integer_to_binary(Value);

        {step_range, Start, End} ->
            <<<<(erlang:integer_to_binary(Start))/binary, "-"/utf8>>/binary,
                (erlang:integer_to_binary(End))/binary>>
    end.

-file("src/automata/cron/builder.gleam", 168).
-spec item_to_string(automata@cron@validator:item()) -> binary().
item_to_string(Item) ->
    case Item of
        {exact, Value} ->
            erlang:integer_to_binary(Value);

        {range, Start, End} ->
            <<<<(erlang:integer_to_binary(Start))/binary, "-"/utf8>>/binary,
                (erlang:integer_to_binary(End))/binary>>;

        {step, Base, Step} ->
            <<<<(step_base_to_string(Base))/binary, "/"/utf8>>/binary,
                (erlang:integer_to_binary(Step))/binary>>
    end.

-file("src/automata/cron/builder.gleam", 158).
-spec selector_to_string(automata@cron@validator:selector()) -> binary().
selector_to_string(Selector) ->
    case Selector of
        any ->
            <<"*"/utf8>>;

        {values, Items} ->
            _pipe = Items,
            _pipe@1 = gleam@list:map(_pipe, fun item_to_string/1),
            gleam@string:join(_pipe@1, <<","/utf8>>)
    end.

-file("src/automata/cron/builder.gleam", 92).
-spec build(builder()) -> {ok, automata@cron@validator:valid_cron()} |
    {error, automata@cron@validator:validation_error()}.
build(Builder) ->
    case first_empty_selector(Builder) of
        {some, Field} ->
            {error, {invalid_list, Field, <<""/utf8>>}};

        none ->
            Rendered = gleam@string:join(
                [selector_to_string(erlang:element(2, Builder)),
                    selector_to_string(erlang:element(3, Builder)),
                    selector_to_string(erlang:element(4, Builder)),
                    selector_to_string(erlang:element(5, Builder)),
                    selector_to_string(erlang:element(6, Builder))],
                <<" "/utf8>>
            ),
            case automata@cron@parser:parse(Rendered) of
                {ok, Raw} ->
                    automata@cron@validator:validate(Raw);

                {error, Error} ->
                    {error, case Error of
                            {unsupported_syntax, Field@1, Value} ->
                                {unsupported_syntax, Field@1, Value};

                            {empty_field, Field@2} ->
                                {invalid_list, Field@2, Rendered};

                            {invalid_expression, Value@1} ->
                                {invalid_list, expression, Value@1};

                            {invalid_field_count, _, _} ->
                                {invalid_list, expression, Rendered}
                        end}
            end
    end.