from typing import Any, Dict, List, Iterable, Iterator, Optional

from . import (AppriseAsset, AppriseAttachment, AppriseConfig, ConfigBase,
               NotifyBase, NotifyFormat, NotifyType)
from .common import ContentLocation

_Server = Union[str, ConfigBase, NotifyBase, AppriseConfig]
_Servers = Union[_Server, Dict[Any, _Server], Iterable[_Server]]
# Can't define this recursively as mypy doesn't support recursive types:
# https://github.com/python/mypy/issues/731
_Tag = Union[str, Iterable[Union[str, Iterable[str]]]]

class Apprise:
    def __init__(
        self,
        servers: _Servers = ...,
        asset: Optional[AppriseAsset] = ...,
        location: Optional[ContentLocation] = ...,
        debug: bool = ...
    ) -> None: ...
    @staticmethod
    def instantiate(
        url: Union[str, Dict[str, NotifyBase]],
        asset: Optional[AppriseAsset] = ...,
        tag: Optional[_Tag] = ...,
        suppress_exceptions: bool = ...
    ) -> NotifyBase: ...
    def add(
        self,
        servers: _Servers = ...,
        asset: Optional[AppriseAsset] = ...,
        tag: Optional[_Tag] = ...
    ) -> bool: ...
    def clear(self) -> None: ...
    def find(self, tag: str = ...) -> Iterator[Apprise]: ...
    def notify(
        self,
        body: str,
        title: str = ...,
        notify_type: NotifyType = ...,
        body_format: NotifyFormat = ...,
        tag: _Tag = ...,
        attach: Optional[AppriseAttachment] = ...,
        interpret_escapes: Optional[bool] = ...
    ) -> bool: ...
    async def async_notify(
        self,
        body: str,
        title: str = ...,
        notify_type: NotifyType = ...,
        body_format: NotifyFormat = ...,
        tag: _Tag = ...,
        attach: Optional[AppriseAttachment] = ...,
        interpret_escapes: Optional[bool] = ...
    ) -> bool: ...
    def details(self, lang: Optional[str] = ...) -> Dict[str, Any]: ...
    def urls(self, privacy: bool = ...) -> Iterable[str]: ...
    def pop(self, index: int) -> ConfigBase: ...
    def __getitem__(self, index: int) -> ConfigBase: ...
    def __bool__(self) -> bool: ...
    def __iter__(self) -> Iterator[ConfigBase]: ...
    def __len__(self) -> int: ...