import grpc, logging
from prometheus_client import Counter, Histogram
from google.protobuf.json_format import MessageToDict
from context.proto.context_pb2 import DeviceId, Empty
from device.proto.device_pb2_grpc import DeviceServiceServicer

LOGGER = logging.getLogger(__name__)

ADDDEVICE_COUNTER_STARTED    = Counter  ('device_adddevice_counter_started',
                                          'Device:AddDevice counter of requests started'  )
ADDDEVICE_COUNTER_COMPLETED  = Counter  ('device_adddevice_counter_completed',
                                          'Device:AddDevice counter of requests completed')
ADDDEVICE_COUNTER_FAILED     = Counter  ('device_adddevice_counter_failed',
                                          'Device:AddDevice counter of requests failed'   )
ADDDEVICE_HISTOGRAM_DURATION = Histogram('device_adddevice_histogram_duration',
                                          'Device:AddDevice histogram of request duration')

CONFIGUREDEVICE_COUNTER_STARTED    = Counter  ('device_configuredevice_counter_started',
                                               'Device:ConfigureDevice counter of requests started'  )
CONFIGUREDEVICE_COUNTER_COMPLETED  = Counter  ('device_configuredevice_counter_completed',
                                               'Device:ConfigureDevice counter of requests completed')
CONFIGUREDEVICE_COUNTER_FAILED     = Counter  ('device_configuredevice_counter_failed',
                                               'Device:ConfigureDevice counter of requests failed'   )
CONFIGUREDEVICE_HISTOGRAM_DURATION = Histogram('device_configuredevice_histogram_duration',
                                               'Device:ConfigureDevice histogram of request duration')

DELETEDEVICE_COUNTER_STARTED    = Counter  ('device_deletedevice_counter_started',
                                            'Device:DeleteDevice counter of requests started'  )
DELETEDEVICE_COUNTER_COMPLETED  = Counter  ('device_deletedevice_counter_completed',
                                            'Device:DeleteDevice counter of requests completed')
DELETEDEVICE_COUNTER_FAILED     = Counter  ('device_deletedevice_counter_failed',
                                            'Device:DeleteDevice counter of requests failed'   )
DELETEDEVICE_HISTOGRAM_DURATION = Histogram('device_deletedevice_histogram_duration',
                                            'Device:DeleteDevice histogram of request duration')

class DeviceServiceServicerImpl(DeviceServiceServicer):
    def __init__(self, database):
        LOGGER.debug('Creating Servicer...')
        self.database = database
        LOGGER.debug('Servicer Created')

    @ADDDEVICE_HISTOGRAM_DURATION.time()
    def AddDevice(self, request, context):
        # request=context.Device(), returns=context.DeviceId()
        ADDDEVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('AddDevice request: {}'.format(str(request)))
            reply = DeviceId(**self.database.add_device(MessageToDict(request)))
            LOGGER.info('AddDevice reply: {}'.format(str(reply)))
            ADDDEVICE_COUNTER_COMPLETED.inc()
            return reply
        except:
            LOGGER.exception('AddDevice exception')
            ADDDEVICE_COUNTER_FAILED.inc()
            context.set_code(grpc.StatusCode.INTERNAL)
            return DeviceId()

    @CONFIGUREDEVICE_HISTOGRAM_DURATION.time()
    def ConfigureDevice(self, request, context):
        # request=context.DeviceConfig(), returns=context.DeviceId()
        CONFIGUREDEVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('ConfigureDevice request: {}'.format(str(request)))
            reply = DeviceId(**self.database.configure_device(MessageToDict(request)))
            LOGGER.info('ConfigureDevice reply: {}'.format(str(reply)))
            CONFIGUREDEVICE_COUNTER_COMPLETED.inc()
            return reply
        except:
            LOGGER.exception('ConfigureDevice exception')
            CONFIGUREDEVICE_COUNTER_FAILED.inc()
            context.set_code(grpc.StatusCode.INTERNAL)
            return DeviceId()

    @DELETEDEVICE_HISTOGRAM_DURATION.time()
    def DeleteDevice(self, request, context):
        # request=context.DeviceId(), returns=context.Empty()
        DELETEDEVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('DeleteDevice request: {}'.format(str(request)))
            reply = Empty(**self.database.delete_device(MessageToDict(request)))
            LOGGER.info('DeleteDevice reply: {}'.format(str(reply)))
            DELETEDEVICE_COUNTER_COMPLETED.inc()
            return reply
        except:
            LOGGER.exception('DeleteDevice exception')
            DELETEDEVICE_COUNTER_FAILED.inc()
            context.set_code(grpc.StatusCode.INTERNAL)
            return Empty()
