from __future__ import annotations
from typing import Any

from .. import builder as b
from .std import _Date, _DateTime, _Number, _String, _Integer, _make_expr
from . import dates, math, strings, decimals, integers, pragmas

def range(*args: _Integer) -> b.Expression:
    # supports range(stop), range(start, stop), range(start, stop, step)
    if len(args) == 1:
        start, stop, step = 0, args[0], 1
    elif len(args) == 2:
        start, stop, step = args[0], args[1], 1
    elif len(args) == 3:
        start, stop, step = args
    else:
        raise ValueError(f"range expects 1, 2, or 3 arguments, got {len(args)}")
    # unlike Python, Rel's range is 1..stop inclusive, so we need to subtract 1 from stop
    return _make_expr("range", cast(b.Int64, start), cast(b.Int64, stop-1), cast(b.Int64, step), b.Int64.ref("res"))

def hash(*args: Any, type=b.Hash) -> b.Expression:
    if len(args) == 0:
        raise ValueError("hash expects at least one argument")
    return _make_expr("hash", b.TupleArg(args), type.ref("res"))

def uuid_to_string(arg:_Integer) -> b.Expression:
    return _make_expr("uuid_to_string", arg, b.String.ref("res"))

def cast(type: b.Concept, arg: _Date|_DateTime|_Number|_String) -> b.Expression:
    return _make_expr("cast", b.TypeRef(type), arg, type.ref("res"))

__all__ = [
    "range",
    "dates",
    "math",
    "strings",
    "decimals",
    "integers",
    "pragmas",
]
