from __future__ import annotations
from typing import Protocol, Coroutine
from .order import Order
import re


DSN_PATTERN = re.compile(r'^(\w+):\/\/\w*:?.*@?.+\/\w+')


class CollectionProtocol(Protocol):
    async def find(self, _filter: dict, *, fields: tuple[str] = ('*',)) -> list[dict]: ...
    async def find_one(self, _filter: dict, *, fields: tuple[str] = ('*',)) -> dict: ...
    async def insert(self, _object: dict, *, returning: tuple[str] = (), typemap: dict | None = None) -> None: ...
    async def update(self, _filter: dict, _object: dict, *, returning: tuple[str] = (), typemap: dict | None = None) -> None: ...
    async def delete(self, _filter) -> None: ...
    async def pop(self, _filter) -> dict: ...
    async def drop(self) -> None: ...
    async def count(self, _filter: dict) -> int: ...
    async def get_size(self) -> int: ...


class ConnectionProtocol(Protocol):
    async def __aenter__(self) -> ConnectionProtocol: ...
    async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...
    def __getattr__(self, key) -> CollectionProtocol: ...
    async def commit(self) -> None: ...
    async def rollback(self) -> None: ...
    async def collections(self) -> tuple[CollectionProtocol]: ...
    async def _fetch(self, query, *args, timeout: float | None = None, record_class=None) -> list: ...


class PoolProtocol(Protocol):
    async def connect(self) -> None: ...
    async def acquire(self) -> ConnectionProtocol: ...
    async def release(self, connection: ConnectionProtocol) -> None: ...
    def on_acquire(self, coroutine: Coroutine[ConnectionProtocol]) -> None: ...


def get_driver_name(dsn: str) -> str:
    return DSN_PATTERN.findall(dsn)[0].lower()
