import concurrent.futures as futures
from contextlib import contextmanager

import load.projects.cloud.loadtesting.server.admin.proto.agent_versions_pb2 as agent_versions_pb2
import load.projects.cloud.loadtesting.server.admin.proto.agent_versions_pb2_grpc as agent_versions_pb2_grpc
import load.projects.cloud.loadtesting.server.admin.proto.db_pb2 as db_pb2
import load.projects.cloud.loadtesting.server.admin.proto.db_pb2_grpc as db_pb2_grpc
import load.projects.cloud.loadtesting.server.admin.proto.log_pb2 as log_pb2
import load.projects.cloud.loadtesting.server.admin.proto.log_pb2_grpc as log_pb2_grpc
import load.projects.cloud.loadtesting.server.admin.proto.profiling_pb2 as profiling_pb2
import load.projects.cloud.loadtesting.server.admin.proto.profiling_pb2_grpc as profiling_pb2_grpc
import load.projects.cloud.loadtesting.server.admin.proto.server_pb2 as server_pb2
import load.projects.cloud.loadtesting.server.admin.proto.server_pb2_grpc as server_pb2_grpc
from grpc_reflection.v1alpha import reflection

import grpc
from load.projects.cloud.loadtesting.server.admin.servicers.agent_versions import AgentVersionsServicer
from load.projects.cloud.loadtesting.server.admin.servicers.db import DBServicer
from load.projects.cloud.loadtesting.server.admin.servicers.log import LogServicer
from load.projects.cloud.loadtesting.server.admin.servicers.profiling import Profiling
from load.projects.cloud.loadtesting.server.admin.servicers.server import ServerInfo
from load.projects.cloud.cloud_helper.grpc_options import COMMON_CHANNEL_OPTIONS


@contextmanager
def adminized(server_to_follow, logging_controller):
    with futures.ThreadPoolExecutor() as pool:
        admin = grpc.server(pool,
                            options=COMMON_CHANNEL_OPTIONS)

        log_pb2_grpc.add_LogServicer_to_server(LogServicer(logging_controller), admin)
        db_pb2_grpc.add_DBServicer_to_server(DBServicer(), admin)
        agent_versions_pb2_grpc.add_AgentVersionsServicer_to_server(AgentVersionsServicer(), admin)
        profiling_pb2_grpc.add_ProfilingServicer_to_server(Profiling(), admin)
        server_pb2_grpc.add_ServerServicer_to_server(ServerInfo(server_to_follow), admin)

        admin.add_insecure_port('[::]:50055')

        names = [
            log_pb2.DESCRIPTOR.services_by_name['Log'].full_name,
            db_pb2.DESCRIPTOR.services_by_name['DB'].full_name,
            agent_versions_pb2.DESCRIPTOR.services_by_name['AgentVersions'].full_name,
            profiling_pb2.DESCRIPTOR.services_by_name['Profiling'].full_name,
            server_pb2.DESCRIPTOR.services_by_name['Server'].full_name,
            reflection.SERVICE_NAME,
        ]

        reflection.enable_server_reflection(names, admin)

        admin.start()

        try:
            yield
        finally:
            admin.stop(grace=None)
