-module(range).
-compile(nowarn_unused_vars).
-compile(nowarn_unused_function).
-export([make_range_step_function/4, integral_range_step/5, range_decimal/3, range_double/3, range_int32/3, range_u_int32/3, range_int64/3, range_u_int64/3, range_big_int/3, range_char/2]).

make_range_step_function(Step, Stop, Zero, Add) ->
    StepComparedWithZero = fable_comparison:compare(Step, Zero),
    begin case fable_comparison:equals(StepComparedWithZero, 0) of
        true ->
            erlang:error(<<"The step of a range cannot be zero"/utf8>>)
        ;
        false ->
            ok
    end,
    begin StepGreaterThanZero = StepComparedWithZero > 0,
    fun(X) ->
        ComparedWithLast = fable_comparison:compare(X, Stop),
        case case case StepGreaterThanZero of
            true ->
                ComparedWithLast =< 0
            ;
            false ->
                false
        end of
            true ->
                true
            ;
            false ->
                case not StepGreaterThanZero of
                    true ->
                        ComparedWithLast >= 0
                    ;
                    false ->
                        false
                end
        end of
            true ->
                {X, Add(X, Step)}
            ;
            false ->
                undefined
        end
end end end
.

integral_range_step(Start, Step, Stop, Zero, Add) ->
    StepFn = make_range_step_function(Step, Stop, Zero, Add),
    seq:delay(fun(UnitVar) ->
        seq:unfold(StepFn, Start)
end)
.

range_decimal(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, fable_decimal:from_parts(0, 0, 0, false, 0), fun(X, Y) ->
        X + Y
end)
.

range_double(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0.0, fun(X, Y) ->
        X + Y
end)
.

range_int32(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0, fun(X, Y) ->
        X + Y
end)
.

range_u_int32(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0, fun(X, Y) ->
        X + Y
end)
.

range_int64(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0, fun(X, Y) ->
        X + Y
end)
.

range_u_int64(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0, fun(X, Y) ->
        X + Y
end)
.

range_big_int(Start, Step, Stop) ->
    integral_range_step(Start, Step, Stop, 0, fun(X, Y) ->
        X + Y
end)
.

range_char(Start, Stop) ->
    seq:delay(fun(UnitVar) ->
        seq:unfold(fun(I) ->
            case I =< Stop of
                true ->
                    {I, I + 1}
                ;
                false ->
                    undefined
            end
end, Start)
end)
.
