"""
"""
from typing import Type

from fastapi import FastAPI
from fastapi_utils.inferring_router import InferringRouter

from .controller_utils import (TEMPLATE_PATH_KEY, VER_KEY, ControllerBase,
                               _get_leaf_controllers,
                               _register_controller_to_router, _http_method)


def register_controllers_to_app(app: FastAPI,
                                controller_base: Type[ControllerBase]) -> None:
    """
    Registers all the api routes inside child controllers of the base
    controller.


    Args:
      app: FastAPI: root FastAPI app
      controller_base: Type[ControllerBase]: base controller class generated by
      create_controller function

    Returns:
    None
    """
    router = InferringRouter()

    controllers = _get_leaf_controllers(controller_base)

    for ctrl in controllers:
        _register_controller_to_router(router, ctrl)

    app.include_router(router)


def create_controller(template_path_prefix: str = "", version: str = "") -> Type[ControllerBase]:
    """
    Create a base controller that can be used as a parent controller for other
    Controllers. Allows the ability to add a path prefix and to version the
    api.

    Args:
      template_path_prefix: str: path prefix for all the controllers. You can
      use template variables
      `version` and `controller` to replace the version 
      version: str:

    Returns:
    Type[ControllerBase]: a class that can be used as a base for other
    controllers.
    """

    class GeneratedController(ControllerBase):
        """ """
        pass

    setattr(GeneratedController, TEMPLATE_PATH_KEY, template_path_prefix)
    setattr(GeneratedController, VER_KEY, version)

    return GeneratedController


class controller:
    """ """

    @staticmethod
    def get(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "get", *args, **kwargs)

    @staticmethod
    def post(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "post", *args, **kwargs)

    @staticmethod
    def put(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "put", *args, **kwargs)

    @staticmethod
    def patch(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "patch", *args, **kwargs)

    @staticmethod
    def delete(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "delete", *args, **kwargs)

    @staticmethod
    def head(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "head", *args, **kwargs)

    @staticmethod
    def options(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "options", *args, **kwargs)

    @staticmethod
    def trace(path: str, *args, **kwargs):
        """

        Args:
          path: str:
          **kwargs: 

        Returns:

        """
        return _http_method(path, "trace", *args, **kwargs)
