# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# Copyright:   (c) 2021 ff. Michael Amrhein (michael@adrhinum.de)
# License:     This program is part of a larger application. For license
#              details please read the file LICENSE.TXT provided together
#              with the application.
# ----------------------------------------------------------------------------
# $Source:$
# $Revision:$

from __future__ import annotations

from abc import abstractmethod
from decimal import Decimal as _StdLibDecimal
from enum import Enum
from fractions import Fraction
from numbers import Complex, Rational, Real
from typing import (
    Any, Optional, Protocol, SupportsFloat, SupportsInt, Tuple, Union,
    overload, )

class SupportsAsIntegerRatio(Protocol):
    @abstractmethod
    def as_integer_ratio(self) -> Tuple[int, int]: ...

SupportsIntOrFloat = Union[SupportsInt, SupportsFloat]
DecValueT = Union[SupportsAsIntegerRatio, SupportsInt, SupportsFloat, str,
                  None]

class Decimal(Rational):
    def __new__(cls, value: DecValueT=..., precision: Optional[int]=...) -> \
            Decimal: ...
    @classmethod
    def from_float(cls: Any, f: Union[float, int]) -> Decimal: ...
    @classmethod
    def from_decimal(cls: Any, d: Union[Decimal, int, _StdLibDecimal]) -> \
            Decimal: ...
    @classmethod
    def from_real(cls: Any, r: Real, exact: bool=...) -> Decimal: ...
    @property
    def precision(self) -> int: ...
    @property
    def magnitude(self) -> int: ...
    @property
    def numerator(self) -> int: ...
    @property
    def denominator(self) -> int: ...
    @property
    def real(self) -> Decimal: ...
    @property
    def imag(self) -> int: ...
    def adjusted(self, precision: Optional[int]=..., rounding: Optional[ROUNDING]=...) -> Decimal: ...
    def quantize(self, quant: Any, rounding: Optional[ROUNDING]=...) -> Rational: ...
    def as_tuple(self) -> Tuple[int, int, int]: ...
    def as_fraction(self) -> Fraction: ...
    def as_integer_ratio(self) -> Tuple[int, int]: ...
    def __copy__(self) -> Decimal: ...
    def __deepcopy__(self, memo: Any) -> Decimal: ...
    def __bytes__(self) -> bytes: ...
    def __format__(self, fmt_spec: str) -> str: ...
    def __eq__(self, other: Any) -> bool: ...
    def __lt__(self, other: Any) -> bool: ...
    def __le__(self, other: Any) -> bool: ...
    def __gt__(self, other: Any) -> bool: ...
    def __ge__(self, other: Any) -> bool: ...
    def __hash__(self) -> int: ...
    def __bool__(self) -> bool: ...
    def __int__(self) -> int: ...
    def __trunc__(self) -> int: ...
    def __float__(self) -> float: ...
    def __pos__(self) -> Decimal: ...
    def __neg__(self) -> Decimal: ...
    def __abs__(self) -> Decimal: ...
    @overload
    def __add__(self, other: int) -> Decimal: ...
    @overload
    def __add__(self, other: Decimal) -> Decimal: ...
    @overload
    def __add__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    @overload
    def __radd__(self, other: int) -> Decimal: ...
    @overload
    def __radd__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    @overload
    def __sub__(self, other: int) -> Decimal: ...
    @overload
    def __sub__(self, other: Decimal) -> Decimal: ...
    @overload
    def __sub__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    @overload
    def __rsub__(self, other: int) -> Decimal: ...
    @overload
    def __rsub__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    @overload
    def __mul__(self, other: int) -> Decimal: ...
    @overload
    def __mul__(self, other: Decimal) -> Decimal: ...
    @overload
    def __mul__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    @overload
    def __rmul__(self, other: int) -> Decimal: ...
    @overload
    def __rmul__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    def __truediv__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    def __rtruediv__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    def __divmod__(self, other: SupportsAsIntegerRatio) -> Tuple[int, Rational]: ...
    def __rdivmod__(self, other: SupportsAsIntegerRatio) -> Tuple[int, Rational]: ...
    def __floordiv__(self, other: SupportsAsIntegerRatio) -> int: ...
    def __rfloordiv__(self, other: SupportsAsIntegerRatio) -> int: ...
    def __mod__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    def __rmod__(self, other: SupportsAsIntegerRatio) -> Rational: ...
    def __pow__(self, other: SupportsIntOrFloat, mod: Any=...) -> Complex: ...
    def __rpow__(self, other: Any, mod: Any=...) -> Complex: ...
    def __floor__(self) -> int: ...
    def __ceil__(self) -> int: ...
    @overload
    def __round__(self, ndigits: None = ...) -> int: ...
    @overload
    def __round__(self, ndigits: int) -> Decimal: ...

class ROUNDING(Enum):
    ROUND_05UP: str = ...
    ROUND_CEILING: str = ...
    ROUND_DOWN: str = ...
    ROUND_FLOOR: str = ...
    ROUND_HALF_DOWN: str = ...
    ROUND_HALF_EVEN: str = ...
    ROUND_HALF_UP: str = ...
    ROUND_UP: str = ...

def get_dflt_rounding_mode() -> ROUNDING: ...
def set_dflt_rounding_mode(rounding: ROUNDING) -> None: ...

ZERO: Decimal
ONE: Decimal
