#from typing import Dict
import grpc, logging
#from common.exceptions.ServiceException import ServiceException
from common.rpc_method_wrapper.Decorator import create_metrics, safe_and_metered_rpc_method
from service.proto.context_pb2 import ConnectionList, Empty, Service, ServiceId #, ServiceList
from service.proto.service_pb2_grpc import ServiceServiceServicer
#from service.service.Tools import check_service_id_request, check_service_request

LOGGER = logging.getLogger(__name__)

SERVICE_NAME = 'Service'
METHOD_NAMES = ['CreateService', 'UpdateService', 'DeleteService',  'GetConnectionList']
METRICS = create_metrics(SERVICE_NAME, METHOD_NAMES)

class ServiceServiceServicerImpl(ServiceServiceServicer):
    def __init__(self):
        LOGGER.debug('Creating Servicer...')
        LOGGER.debug('Servicer Created')

    #@safe_and_metered_rpc_method(METRICS, LOGGER)
    #def GetServiceList(self, request : Empty, context : grpc.ServicerContext) -> ServiceList:
    #    db_context_uuids = self.database.contexts.get()
    #    json_services = []
    #    for db_context_uuid in db_context_uuids:
    #        db_context = self.database.context(db_context_uuid)
    #        json_services.extend(db_context.dump_services())
    #    return ServiceList(cs=json_services)

    @safe_and_metered_rpc_method(METRICS, LOGGER)
    def CreateService(self, request : Service, context : grpc.ServicerContext) -> ServiceId:
        #context_id, service_id, service_type, service_config, service_state, db_endpoints, constraint_tuples = \
        #    check_service_request('CreateService', request, self.database, LOGGER)
        #db_context = self.database.context(context_id)
        #db_service = db_context.service(service_id)
        #db_service.create(service_type, service_config, service_state)
        #for db_endpoint in db_endpoints:
        #    service_endpoint_id = '{}:{}/{}'.format(
        #        db_endpoint.topology_uuid, db_endpoint.device_uuid, db_endpoint.endpoint_uuid)
        #    db_service.endpoint(service_endpoint_id).create(db_endpoint)
        #for cons_type,cons_value in constraint_tuples: db_service.constraint(cons_type).create(cons_value)
        #return ServiceId(**db_service.dump_id())
        return ServiceId()

    @safe_and_metered_rpc_method(METRICS, LOGGER)
    def UpdateService(self, request : Service, context : grpc.ServicerContext) -> ServiceId:
        #context_id, service_id, service_type, service_config, service_state, db_endpoints, constraint_tuples = \
        #    check_service_request('UpdateService', request, self.database, LOGGER)
        #db_context = self.database.context(context_id)
        #db_service = db_context.service(service_id)
        #db_service.update(update_attributes={
        #    'service_type'  : service_type,
        #    'service_config': service_config,
        #    'service_state' : service_state,
        #})
        ## Update service constraints; first add missing, then remove existing, but not added to Service
        #db_service_constraint_types = set(db_service.constraints.get())
        #for constraint_type,constraint_value in constraint_tuples:
        #    if constraint_type in db_service_constraint_types:
        #        db_service.constraint(constraint_type).update(update_attributes={
        #            'constraint_value': constraint_value
        #        })
        #    else:
        #        db_service.constraint(constraint_type).create(constraint_value)
        #    db_service_constraint_types.discard(constraint_type)
        #for constraint_type in db_service_constraint_types:
        #    db_service.constraint(constraint_type).delete()
        ## Update service endpoints; first add missing, then remove existing, but not added to Service
        #db_service_endpoint_uuids = set(db_service.endpoints.get())
        #for db_endpoint in db_endpoints:
        #    service_endpoint_id = '{}:{}/{}'.format(
        #        db_endpoint.topology_uuid, db_endpoint.device_uuid, db_endpoint.endpoint_uuid)
        #    if service_endpoint_id not in db_service_endpoint_uuids:
        #        db_service.endpoint(service_endpoint_id).create(db_endpoint)
        #    db_service_endpoint_uuids.discard(service_endpoint_id)
        #for db_service_endpoint_uuid in db_service_endpoint_uuids:
        #    db_service.endpoint(db_service_endpoint_uuid).delete()
        #return ServiceId(**db_service.dump_id())
        return ServiceId()

    @safe_and_metered_rpc_method(METRICS, LOGGER)
    def DeleteService(self, request : ServiceId, context : grpc.ServicerContext) -> Empty:
        #context_id, service_id = check_service_id_request('DeleteService', request, self.database, LOGGER)
        #db_context = self.database.context(context_id)
        #db_service = db_context.service(service_id)
        #db_service.delete()
        return Empty()

    #@safe_and_metered_rpc_method(METRICS, LOGGER)
    #def GetServiceById(self, request : ServiceId, context : grpc.ServicerContext) -> Service:
    #    context_id, service_id = check_service_id_request('GetServiceById', request, self.database, LOGGER)
    #    db_context = self.database.context(context_id)
    #    db_service = db_context.service(service_id)
    #    return Service(**db_service.dump())

    @safe_and_metered_rpc_method(METRICS, LOGGER)
    def GetConnectionList(self, request : Empty, context : grpc.ServicerContext) -> ConnectionList:
        #raise ServiceException(grpc.StatusCode.UNIMPLEMENTED, 'RPC GetConnectionList() not implemented')
        return ConnectionList()
