"""Base class for token generators.

Version Added:
    3.0
"""

from typing import Any, Dict, Optional


class BaseTokenGenerator:
    """A base class for token generators.

    These are used to generate and validate access tokens.

    At the very least, subclasses must set:

    * :py:attr:`token_generator_id`

    as well as implement the :py:meth:`create_token` and
    :py:meth:`validate_token` methods.

    Version Added:
        3.0
    """

    #: The unique ID of the token generator, for registration purposes.
    #:
    #: Type:
    #:     str
    token_generator_id: Optional[str] = None

    def create_token(
        self,
        token_info: Dict[str, Any] = {},
        **kwargs,
    ) -> str:
        """Create a new token.

        Subclasses must override this to actually create the token.

        Args:
            token_info (dict, optional):
                A dictionary that contains information about the
                token.

            **kwargs (dict):
                Additional keyword arguments.

        Returns:
            str:
            The token that was created.

        Raises:
            NotImplementedError:
                The subclass did not implement this method.
        """
        raise NotImplementedError

    def validate_token(
        self,
        token: str,
        token_info: Dict[str, Any] = {},
        **kwargs,
    ) -> bool:
        """Validate the token.

        This should return a bool indicating whether the given token
        is a valid token that could have been generated by this generator.

        Subclasses must override this to actually validate the token.

        Args:
            token (str):
                The token to validate.

            token_info (dict, optional):
                A dictionary that contains information about the
                token.

            **kwargs (dict):
                Additional keyword arguments.

        Returns:
            bool:
            Whether the token is a valid token from this generator.

        Raises:
            NotImplementedError:
                The subclass did not implement this method.
        """
        raise NotImplementedError
