import datetime
from typing import Final, Literal, overload
from typing_extensions import Self

from pymeeus.Angle import Angle

DAY2SEC: Final = 86400.0
DAY2MIN: Final = 1440.0
DAY2HOURS: Final = 24.0
LEAP_TABLE: Final[dict[float, int]]

class Epoch:
    @overload
    def __init__(self) -> None: ...
    @overload
    def __init__(
        self, year: int, month: int, day: int, /, *time: float, leap_seconds: float = 0, local: bool = False, utc: bool = False
    ) -> None: ...
    @overload
    def __init__(
        self,
        a: float | Epoch | list[float] | tuple[float, ...] | datetime.date,
        /,
        *,
        leap_seconds: float = 0,
        local: bool = False,
        utc: bool = False,
    ) -> None: ...

    def __hash__(self) -> int: ...

    @overload
    def set(self) -> None: ...
    @overload
    def set(
        self, year: int, month: int, day: int, /, *time: float, leap_seconds: float = 0, local: bool = False, utc: bool = False
    ) -> None: ...
    @overload
    def set(
        self,
        a: float | Epoch | list[float] | tuple[float, ...] | datetime.date,
        /,
        *,
        leap_seconds: float = 0,
        local: bool = False,
        utc: bool = False,
    ) -> None: ...

    @overload
    @overload
    @staticmethod
    def check_input_date(
        a: Epoch | list[float] | tuple[float, ...] | datetime.date,
        /,
        *,
        leap_seconds: float = 0,
        local: bool = False,
        utc: bool = False,
    ) -> Epoch: ...
    @overload
    @staticmethod
    def check_input_date(
        year: int, month: int, day: int, /, *, leap_seconds: float = 0, local: bool = False, utc: bool = False
    ) -> Epoch: ...

    @staticmethod
    def is_julian(year: int, month: int, day: int) -> bool: ...
    def julian(self) -> bool: ...

    @overload
    @staticmethod
    def get_month(month: float | str, as_string: Literal[True]) -> str: ...
    @overload
    @staticmethod
    def get_month(month: float | str, as_string: Literal[False] | None = False) -> int: ...

    @staticmethod
    def is_leap(year: float) -> bool: ...
    def leap(self) -> bool: ...
    @staticmethod
    def get_doy(yyyy: int, mm: int, dd: int) -> float: ...
    def doy(self) -> float: ...
    @staticmethod
    def doy2date(year: int, doy: float) -> tuple[int, int, float]: ...
    @staticmethod
    def leap_seconds(year: int, month: int) -> int: ...
    @staticmethod
    def get_last_leap_second() -> tuple[int, int, float, int]: ...
    @staticmethod
    def utc2local() -> float: ...
    @staticmethod
    def easter(year: float) -> tuple[int, int]: ...
    @staticmethod
    def jewish_pesach(year: float) -> tuple[int, int]: ...
    @staticmethod
    def moslem2gregorian(year: float, month: float, day: float) -> tuple[int, int, int]: ...
    @staticmethod
    def gregorian2moslem(year: float, month: float, day: float) -> tuple[int, int, int]: ...
    def get_date(self, *, utc: bool = False, leap_seconds: float = 0.0, local: bool = ...) -> tuple[int, int, float]: ...
    def get_full_date(
        self, *, utc: bool = False, leap_seconds: float = 0.0, local: bool = ...
    ) -> tuple[int, int, int, int, int, float]: ...
    @staticmethod
    def tt2ut(year: int, month: int) -> float: ...

    @overload
    def dow(self, as_string: Literal[True]) -> str: ...
    @overload
    def dow(self, as_string: Literal[False] | None = False) -> int: ...

    def mean_sidereal_time(self) -> float: ...
    def apparent_sidereal_time(self, true_obliquity: float | Angle, nutation_longitude: float | Angle) -> float: ...
    def mjd(self) -> float: ...
    def jde(self) -> float: ...
    def year(self) -> float: ...
    def rise_set(self, latitude: Angle, longitude: Angle, altitude: float = 0.0) -> tuple[Epoch, Epoch]: ...
    def __call__(self) -> float: ...
    def __add__(self, b: float) -> Epoch: ...

    @overload
    def __sub__(self, b: float) -> Epoch: ...
    @overload
    def __sub__(self, b: Epoch) -> float: ...

    def __iadd__(self, b: float) -> Self: ...
    def __isub__(self, b: float) -> Self: ...  # type: ignore[misc] # __sub__ and __isub__ are incompatible
    def __radd__(self, b: float) -> Epoch: ...
    def __int__(self) -> int: ...
    def __float__(self) -> float: ...
    def __eq__(self, b: float | Epoch) -> bool: ...  # type: ignore[override]
    def __ne__(self, b: float | Epoch) -> bool: ...  # type: ignore[override]
    def __lt__(self, b: float | Epoch) -> bool: ...
    def __ge__(self, b: float | Epoch) -> bool: ...
    def __gt__(self, b: float | Epoch) -> bool: ...
    def __le__(self, b: float | Epoch) -> bool: ...

JDE2000: Epoch

def main() -> None: ...
