
from typing import Generator, Optional, Tuple
from ...transport.request import Request
from ...transport.response import Response


class BaseHandler:
    """
    A class for sending the request through the chain of handlers.

    :ivar BaseHandler _next_handler: The next handler in the chain.
    """

    def __init__(self):
        """
        Initialize a new instance of BaseHandler.
        """
        self._next_handler = None

    def handle(
        self, request: Request
    ) -> Tuple[Optional[Response], Optional[Exception]]:
        """
        Process the given request and return a response or an error.
        This method must be implemented by all subclasses.

        :param Request request: The request to handle.
        :return: The response and any error that occurred.
        :rtype: Tuple[Optional[Response], Optional[Exception]]
        """
        raise NotImplementedError()

    def stream(
        self, request: Request
    ) -> Generator[Tuple[Optional[Response], Optional[Exception]], None, None]:
        """
        Stream the given request and return a response or an error.
        This method must be implemented by all subclasses.

        :param Request request: The request to stream.
        :return: The response and any error that occurred.
        :rtype: Generator[Tuple[Optional[Response], Optional[Exception]], None, None]
        """
        raise NotImplementedError()

    def set_next(self, handler: "BaseHandler"):
        """
        Set the next handler in the chain.

        :param BaseHandler handler: The next handler.
        """
        self._next_handler = handler
