
"""
The RelationalAI Semantics Standard Library.
"""
from ..frontend.base import Variable, Literal, Expression
from ...util.error import warn, exc, source, Part
from ...util.source import SourcePos
from decimal import Decimal as PyDecimal
import datetime as dt
from typing import Any, Union

__include_in_docs__ = True

#------------------------------------------------------
# Helpers
#------------------------------------------------------

def _deprecated_library(library, replacement=None, example=None):
    replacement_message = ""
    parts: list[Part] = [source(SourcePos.new())]
    if replacement is not None:
        replacement_message = f" Use '{replacement}' instead."
    if example is not None:
        parts.append(f'For example: [cyan]{example}[/cyan]')
    warn("Deprecated library", f"The {library} library is deprecated.{replacement_message}", parts)

def _deprecated_function(func_name, replacement=None, example=None):
    replacement_message = ""
    parts: list[Part] = [source(SourcePos.new())]
    if replacement is not None:
        replacement_message = f" Use '{replacement}' instead."
    if example is not None:
        parts.append(f'For example: [cyan]{example}[/cyan]')
    warn("Deprecated function", f"The function '{func_name}' is deprecated.{replacement_message}", parts)

def _function_not_implemented(func_name: str):
    parts: list[Part] = [source(SourcePos.new())]
    exc("Function not implemented", f"The function '{func_name}' is not yet implemented in PyRel.", parts)

DateTimeValue = Union[Variable, dt.datetime]
""" A type representing a datetime value, which can be a literal `datetime.datetime` or a `Variable` resulting from
some other expression which will evaluate to a datetime. """
DateValue = Union[Variable, dt.date]
""" A type representing a date value, which can be a literal `datetime.date` or a `Variable` resulting from
some other expression which will evaluate to a date. """
FloatValue = Union[Variable, float]
""" A type representing a float value, which can be a literal `float` or a `Variable` resulting from
some other expression which will evaluate to a float. """
IntegerValue = Union[Variable, int]
""" A type representing an integer value, which can be a literal `int` or a `Variable` resulting from
some other expression which will evaluate to an integer. """
NumberValue = Union[Variable, float, int, PyDecimal]
""" A type representing a number value, which can be a literal `float`, `int`, or `Decimal`, or a `Variable` resulting from
some other expression which will evaluate to a number. """
StringValue = Union[Variable, str]
""" A type representing a string value, which can be a literal `str` or a `Variable` resulting from
some other expression which will evaluate to a string. """


def _get_number_value(value: Any) -> Union[float, int, PyDecimal, None]:
    """ If the value is a number literal, return its value as a Python number. """
    if isinstance(value, (float, int, PyDecimal)):
        return value
    if isinstance(value, Literal):
        return _get_number_value(value._value)
    return None


#------------------------------------------------------
# Libraries
#------------------------------------------------------
# Import submodules after type aliases are defined to avoid circular imports
from . import aggregates, common, datetime, decimals, integers, math, numbers, re, strings, constraints  # noqa: E402

__all__ = [
    "aggregates",
    "common",
    "constraints",
    "datetime",
    "decimals",
    "integers",
    "math",
    "numbers",
    "re",
    "strings",
]

#------------------------------------------------------
# Deprecated functions
#------------------------------------------------------

def range(*args: IntegerValue) -> Expression:
    _deprecated_function("std.range", "std.common.range")
    return common.range(*args)
