from typing import Callable, List

from fastapi import FastAPI as _FastAPI
from starlette.applications import Starlette as _Starlette
from starlette.types import ASGIApp

import uvicore
from uvicore.contracts import Server as ServerInterface
from uvicore.support.dumper import dd, dump

# This is our actual FastAPI Server
# Can only have one server, can't be both FastAPI and/or Starlette
# The FastAPI server inherits Starlette server but extends it with
# extra options for openapi, so we must use that as our base http app

# In classic FastAIP example, this is same as
# app = FastAPI(), but I call it app.http

# Bound from service provider instead of decorator


# @uvicore.service('uvicore.http.server._Server',
#     aliases=['http', 'HTTP'],
#     singleton=True,
#     kwargs={
#         'debug': uvicore.config('app.debug'),
#         'title': uvicore.config('app.openapi.title'),
#         'version': uvicore.app.version,
#         'openapi_url': uvicore.config('app.openapi.url'),
#         'docs_url': uvicore.config('app.openapi.docs_url'),
#         'redoc_url': uvicore.config('app.openapi.redoc_url'),
#     },
# )
# class _Server(_FastAPI):
#     @property
#     def server(self) -> _FastAPI:
#         return self


    # def include_router(self, router, *, prefix: str = '', tags: List[str] = None) -> None:
    #     # _server is a FastAPI application.  If you look at FastAPIs include_router
    #     # it automatically detects if the the actual Router is FastAPI or Starlette
    #     # and handles the including of the routers routes differently!

    #     for route in router.routes:
    #         self.add_route(
    #             path=route.pathroute)

        # self._server.include_router(
        #     router=router,
        #     prefix=prefix,
        #     tags=tags,
        # )


        # self,
        # path: str,
        # route: typing.Callable,
        # methods: typing.List[str] = None,
        # name: str = None,
        # include_in_schema: bool = True,






# Example of abstratsion
class ServerXXXX(ServerInterface):
    """HTTP Server private class.

    Do not import from this location.
    Use the uvicore.app.http singleton global instead."""

    @property
    def server(self) -> _FastAPI:
        return self._server

    def __init__(self, debug: bool, title: str, version: str, openapi_url: str, docs_url: str, redoc_url: str):

        # Fireup FastAPI HTTP Core
        self._server = _FastAPI(
            debug=debug,
            title=title,
            version=version,
            openapi_url=openapi_url,
            docs_url=docs_url,
            redoc_url=redoc_url,
        )

    def include_router(self, router, *, prefix: str = '', tags: List[str] = None) -> None:
        # _server is a FastAPI application.  If you look at FastAPIs include_router
        # it automatically detects if the the actual Router is FastAPI or Starlette
        # and handles the including of the routers routes differently!
        self._server.include_router(
            router=router,
            prefix=prefix,
            tags=tags,
        )

    def mount(self, path: str, app: ASGIApp, name: str = None) -> None:
        self._server.mount(path=path, app=app, name=name)

    def on_event(self, event_type: str) -> Callable:
        return self._server.on_event(event_type)


# IoC Class Instance
# No because not to be used by the public
#Server: ServerInterface = uvicore.ioc.make('Http')

# Public API for import * and doc gens
#__all__ = ['_Server']
