import grpc, logging
from prometheus_client import Counter, Histogram
from common.database.api.Database import Database
from common.exceptions.ServiceException import ServiceException
from context.proto.context_pb2 import Empty, Topology
from context.proto.context_pb2_grpc import ContextServiceServicer

LOGGER = logging.getLogger(__name__)

DEFAULT_CONTEXT_ID = 'admin'
DEFAULT_TOPOLOGY_ID = 'admin'

GETTOPOLOGY_COUNTER_STARTED    = Counter  ('context_gettopology_counter_started',
                                          'Context:GetTopology counter of requests started'  )
GETTOPOLOGY_COUNTER_COMPLETED  = Counter  ('context_gettopology_counter_completed',
                                          'Context:GetTopology counter of requests completed')
GETTOPOLOGY_COUNTER_FAILED     = Counter  ('context_gettopology_counter_failed',
                                          'Context:GetTopology counter of requests failed'   )
GETTOPOLOGY_HISTOGRAM_DURATION = Histogram('context_gettopology_histogram_duration',
                                          'Context:GetTopology histogram of request duration')

class ContextServiceServicerImpl(ContextServiceServicer):
    def __init__(self, database : Database):
        LOGGER.debug('Creating Servicer...')
        self.database = database
        LOGGER.debug('Servicer Created')

    @GETTOPOLOGY_HISTOGRAM_DURATION.time()
    def GetTopology(self, request : Empty, grpc_context : grpc.ServicerContext) -> Topology:
        GETTOPOLOGY_COUNTER_STARTED.inc()
        try:
            LOGGER.debug('GetTopology request: {}'.format(str(request)))

            # ----- Validate request data and pre-conditions -----------------------------------------------------------
            db_context = self.database.context(DEFAULT_CONTEXT_ID).create()
            db_topology = db_context.topology(DEFAULT_TOPOLOGY_ID).create()

            # ----- Retrieve data from the database --------------------------------------------------------------------
            json_topology = db_topology.dump()

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = Topology(**json_topology)
            LOGGER.debug('GetTopology reply: {}'.format(str(reply)))
            GETTOPOLOGY_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('GetTopology exception')               # pragma: no cover
            GETTOPOLOGY_COUNTER_FAILED.inc()                        # pragma: no cover
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))    # pragma: no cover
