import datetime
import sys
from typing import Any, Union, Tuple

import numpy as np

if sys.version_info >= (3, 8):
    from typing import Literal
else:
    from typing_extensions import Literal

ClosedOption = Literal['left', 'right', 'both', 'neither']
# According to docs "ValueError: Only numeric, Timestamp and Timedelta endpoints are allowed when constructing an Interval."
IntervalBound = Union[int, float, np.integer, np.complex_, datetime.datetime, datetime.timedelta]

class IntervalMixin:
    @property
    def closed_left(self) -> bool: ...
    @property
    def closed_right(self) -> bool: ...
    @property
    def open_left(self) -> bool: ...
    @property
    def open_right(self) -> bool: ...
    @property
    def mid(self) -> Any: ...
    @property
    def length(self) -> Any: ...
    @property
    def is_empty(self) -> bool: ...

class Interval(IntervalMixin):
    @property
    def closed(self) -> str: ...
    @property
    def left(self) -> IntervalBound: ...
    @property
    def right(self) -> IntervalBound: ...
    def __init__(self, left: IntervalBound, right: IntervalBound, closed: ClosedOption = ...) -> None: ...
    def __hash__(self) -> int: ...
    def __contains__(self, key: Any) -> bool: ...
    def __repr__(self) -> str: ...
    def __str__(self) -> str: ...

    def __add__(self, y: Any) -> Interval: ...
    def __sub__(self, y: Any) -> Interval: ...
    def __mul__(self, y: Any) -> Interval: ...
    def __truediv__(self, y: Any) -> Interval: ...
    def __floordiv__(self, y: Any) -> Interval: ...
    def overlaps(self, other: Interval) -> bool: ...


def intervals_to_interval_bounds(intervals: np.ndarray, validate_closed: bool = ...) -> Tuple[np.ndarray, np.ndarray, str]: ...


class IntervalTree: ...