from typing import Any
from typing import Callable
from typing import Generator
from typing import Mapping
from typing import NoReturn
from typing import Optional
from typing import TypeVar

from .base import ProxyComparable
from .base import StartableContext
from .result import AsyncResult
from ...engine import Result
from ...engine import Transaction
from ...future import Connection
from ...future import Engine
from ...sql import Executable

_TAsyncConnection = TypeVar("_TAsyncConnection", bound=AsyncConnection)
_TAsyncTransaction = TypeVar("_TAsyncTransaction", bound=AsyncTransaction)

def create_async_engine(*arg: Any, **kw: Any) -> AsyncEngine: ...

class AsyncConnectable: ...

class AsyncConnection(ProxyComparable, StartableContext, AsyncConnectable):
    # copied from future.Connection via create_proxy_methods
    @property
    def closed(self) -> bool: ...
    @property
    def invalidated(self) -> bool: ...
    dialect: Any
    @property
    def default_isolation_level(self) -> Any: ...
    # end copied

    engine: AsyncEngine = ...
    sync_engine: Engine = ...
    sync_connection: Optional[Connection] = ...
    def __init__(
        self,
        async_engine: AsyncEngine,
        sync_connection: Optional[Connection] = ...,
    ) -> None: ...
    async def start(self: _TAsyncConnection) -> _TAsyncConnection: ...
    @property
    def connection(self) -> NoReturn: ...
    async def get_raw_connection(self) -> Any: ...
    @property
    def info(self) -> Mapping[Any, Any]: ...
    def begin(self) -> AsyncTransaction: ...
    def begin_nested(self) -> AsyncTransaction: ...
    async def invalidate(self, exception: Optional[Any] = ...) -> None: ...
    async def get_isolation_level(self) -> Any: ...
    async def set_isolation_level(self) -> Any: ...
    def in_transaction(self) -> bool: ...
    def in_nested_transaction(self) -> bool: ...
    def get_transaction(self) -> Optional[AsyncTransaction]: ...
    def get_nested_transaction(self) -> Optional[AsyncTransaction]: ...
    async def execution_options(
        self: _TAsyncConnection, **opt: Any
    ) -> _TAsyncConnection: ...
    async def commit(self) -> None: ...
    async def rollback(self) -> None: ...
    async def close(self) -> None: ...
    async def exec_driver_sql(
        self,
        statement: str,
        parameters: Optional[Mapping[Any, Any]] = ...,
        execution_options: Mapping[Any, Any] = ...,
    ) -> Result: ...
    async def stream(
        self,
        statement: Executable,
        parameters: Optional[Mapping[Any, Any]] = ...,
        execution_options: Mapping[Any, Any] = ...,
    ) -> AsyncResult: ...
    async def execute(
        self,
        statement: Executable,
        parameters: Optional[Mapping[Any, Any]] = ...,
        execution_options: Mapping[Any, Any] = ...,
    ) -> Result: ...
    async def scalar(
        self,
        statement: Executable,
        parameters: Optional[Mapping[Any, Any]] = ...,
        execution_options: Mapping[Any, Any] = ...,
    ) -> Any: ...
    async def run_sync(
        self, fn: Callable[..., Any], *arg: Any, **kw: Any
    ) -> Any: ...
    def __await__(
        self: _TAsyncConnection,
    ) -> Generator[Any, None, _TAsyncConnection]: ...
    async def __aexit__(
        self, type_: Any, value: Any, traceback: Any
    ) -> None: ...

class AsyncEngine(ProxyComparable, AsyncConnectable):
    # copied from future.Engine by create_proxy_methods
    def clear_compiled_cache(self) -> None: ...
    def update_execution_options(self, **opt: Any) -> None: ...
    def get_execution_options(self) -> Mapping[Any, Any]: ...
    # end copied
    class _trans_ctx(StartableContext):
        conn: AsyncConnection = ...
        def __init__(self, conn: AsyncConnection) -> None: ...
        transaction: Any = ...
        async def start(self) -> AsyncConnection: ...  # type: ignore[override]
        def __await__(self) -> Generator[Any, None, AsyncConnection]: ...  # type: ignore[override]
        async def __aexit__(
            self, type_: Any, value: Any, traceback: Any
        ) -> None: ...
    sync_engine: Engine = ...
    def __init__(self, sync_engine: Engine) -> None: ...
    def begin(self) -> _trans_ctx: ...
    def connect(self) -> AsyncConnection: ...
    async def raw_connection(self) -> Any: ...
    def execution_options(self, **opt: Any) -> AsyncEngine: ...
    async def dispose(self) -> None: ...

class AsyncTransaction(ProxyComparable, StartableContext):
    connection: AsyncConnection = ...
    sync_transaction: Optional[Transaction] = ...
    nested: bool = ...
    def __init__(
        self, connection: AsyncConnection, nested: bool = ...
    ) -> None: ...
    @property
    def is_valid(self) -> bool: ...
    @property
    def is_active(self) -> bool: ...
    async def close(self) -> None: ...
    async def rollback(self) -> None: ...
    async def commit(self) -> None: ...
    async def start(self: _TAsyncTransaction) -> _TAsyncTransaction: ...
    async def __aexit__(
        self, type_: Any, value: Any, traceback: Any
    ) -> None: ...
