import grpc, logging
from prometheus_client import Counter, Histogram
from common.database.api.Database import Database
from common.exceptions.ServiceException import ServiceException
from compute.proto.compute_pb2_grpc import ComputeServiceServicer
from compute.proto.context_pb2 import AuthenticationResult, Empty, TeraFlowController
from compute.proto.service_pb2 import Service, ServiceId, ServiceIdList, ServiceState

LOGGER = logging.getLogger(__name__)

CHECKCREDENTIALS_COUNTER_STARTED    = Counter(
    'compute_checkcredentials_counter_started',
    'Compute:CheckCredentials counter of requests started')
CHECKCREDENTIALS_COUNTER_COMPLETED  = Counter(
    'compute_checkcredentials_counter_completed',
    'Compute:CheckCredentials counter of requests completed')
CHECKCREDENTIALS_COUNTER_FAILED     = Counter(
    'compute_checkcredentials_counter_failed',
    'Compute:CheckCredentials counter of requests failed')
CHECKCREDENTIALS_HISTOGRAM_DURATION = Histogram(
    'compute_checkcredentials_histogram_duration',
    'Compute:CheckCredentials histogram of request duration')

GETCONNECTIVITYSERVICESTATUS_COUNTER_STARTED    = Counter(
    'compute_getconnectivityservicestatus_counter_started',
    'Compute:GetConnectivityServiceStatus counter of requests started')
GETCONNECTIVITYSERVICESTATUS_COUNTER_COMPLETED  = Counter(
    'compute_getconnectivityservicestatus_counter_completed',
    'Compute:GetConnectivityServiceStatus counter of requests completed')
GETCONNECTIVITYSERVICESTATUS_COUNTER_FAILED     = Counter(
    'compute_getconnectivityservicestatus_counter_failed',
    'Compute:GetConnectivityServiceStatus counter of requests failed')
GETCONNECTIVITYSERVICESTATUS_HISTOGRAM_DURATION = Histogram(
    'compute_getconnectivityservicestatus_histogram_duration',
    'Compute:GetConnectivityServiceStatus histogram of request duration')

CREATECONNECTIVITYSERVICE_COUNTER_STARTED    = Counter(
    'compute_createconnectivityservice_counter_started',
    'Compute:CreateConnectivityService counter of requests started'  )
CREATECONNECTIVITYSERVICE_COUNTER_COMPLETED  = Counter(
    'compute_createconnectivityservice_counter_completed',
    'Compute:CreateConnectivityService counter of requests completed')
CREATECONNECTIVITYSERVICE_COUNTER_FAILED     = Counter(
    'compute_createconnectivityservice_counter_failed',
    'Compute:CreateConnectivityService counter of requests failed')
CREATECONNECTIVITYSERVICE_HISTOGRAM_DURATION = Histogram(
    'compute_createconnectivityservice_histogram_duration',
    'Compute:CreateConnectivityService histogram of request duration')

EDITCONNECTIVITYSERVICE_COUNTER_STARTED    = Counter(
    'compute_editconnectivityservice_counter_started',
    'Compute:EditConnectivityService counter of requests started')
EDITCONNECTIVITYSERVICE_COUNTER_COMPLETED  = Counter(
    'compute_editconnectivityservice_counter_completed',
    'Compute:EditConnectivityService counter of requests completed')
EDITCONNECTIVITYSERVICE_COUNTER_FAILED     = Counter(
    'compute_editconnectivityservice_counter_failed',
    'Compute:EditConnectivityService counter of requests failed')
EDITCONNECTIVITYSERVICE_HISTOGRAM_DURATION = Histogram(
    'compute_editconnectivityservice_histogram_duration',
    'Compute:EditConnectivityService histogram of request duration')

DELETECONNECTIVITYSERVICE_COUNTER_STARTED    = Counter(
    'compute_deleteconnectivityservice_counter_started',
    'Compute:DeleteConnectivityService counter of requests started')
DELETECONNECTIVITYSERVICE_COUNTER_COMPLETED  = Counter(
    'compute_deleteconnectivityservice_counter_completed',
    'Compute:DeleteConnectivityService counter of requests completed')
DELETECONNECTIVITYSERVICE_COUNTER_FAILED     = Counter(
    'compute_deleteconnectivityservice_counter_failed',
    'Compute:DeleteConnectivityService counter of requests failed')
DELETECONNECTIVITYSERVICE_HISTOGRAM_DURATION = Histogram(
    'compute_deleteconnectivityservice_histogram_duration',
    'Compute:DeleteConnectivityService histogram of request duration')

GETALLACTIVECONNECTIVITYSERVICES_COUNTER_STARTED    = Counter(
    'compute_getallactiveconnectivityservices_counter_started',
    'Compute:GetAllActiveConnectivityServices counter of requests started')
GETALLACTIVECONNECTIVITYSERVICES_COUNTER_COMPLETED  = Counter(
    'compute_getallactiveconnectivityservices_counter_completed',
    'Compute:GetAllActiveConnectivityServices counter of requests completed')
GETALLACTIVECONNECTIVITYSERVICES_COUNTER_FAILED     = Counter(
    'compute_getallactiveconnectivityservices_counter_failed',
    'Compute:GetAllActiveConnectivityServices counter of requests failed')
GETALLACTIVECONNECTIVITYSERVICES_HISTOGRAM_DURATION = Histogram(
    'compute_getallactiveconnectivityservices_histogram_duration',
    'Compute:GetAllActiveConnectivityServices histogram of request duration')

CLEARALLCONNECTIVITYSERVICES_COUNTER_STARTED    = Counter(
    'compute_clearallconnectivityservices_counter_started',
    'Compute:ClearAllConnectivityServices counter of requests started')
CLEARALLCONNECTIVITYSERVICES_COUNTER_COMPLETED  = Counter(
    'compute_clearallconnectivityservices_counter_completed',
    'Compute:ClearAllConnectivityServices counter of requests completed')
CLEARALLCONNECTIVITYSERVICES_COUNTER_FAILED     = Counter(
    'compute_clearallconnectivityservices_counter_failed',
    'Compute:ClearAllConnectivityServices counter of requests failed')
CLEARALLCONNECTIVITYSERVICES_HISTOGRAM_DURATION = Histogram(
    'compute_clearallconnectivityservices_histogram_duration',
    'Compute:ClearAllConnectivityServices histogram of request duration')


class ComputeServiceServicerImpl(ComputeServiceServicer):
    def __init__(self):
        LOGGER.info('Creating Servicer...')
        LOGGER.info('Servicer Created')

    @CHECKCREDENTIALS_HISTOGRAM_DURATION.time()
    def check_credentials(
        self, request : TeraFlowController, grpc_context : grpc.ServicerContext) -> AuthenticationResult:

        CHECKCREDENTIALS_COUNTER_STARTED.inc()
        try:
            LOGGER.info('check_credentials request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = AuthenticationResult()
            LOGGER.info('check_credentials reply: {}'.format(str(reply)))
            CHECKCREDENTIALS_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('check_credentials exception')
            CHECKCREDENTIALS_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('check_credentials exception')
            CHECKCREDENTIALS_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @GETCONNECTIVITYSERVICESTATUS_HISTOGRAM_DURATION.time()
    def get_connectivity_service_status(
        self, request : ServiceId, grpc_context : grpc.ServicerContext) -> ServiceState:

        GETCONNECTIVITYSERVICESTATUS_COUNTER_STARTED.inc()
        try:
            LOGGER.info('get_connectivity_service_status request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = ServiceState()
            LOGGER.info('get_connectivity_service_status reply: {}'.format(str(reply)))
            GETCONNECTIVITYSERVICESTATUS_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('get_connectivity_service_status exception')
            GETCONNECTIVITYSERVICESTATUS_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('get_connectivity_service_status exception')
            GETCONNECTIVITYSERVICESTATUS_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @CREATECONNECTIVITYSERVICE_HISTOGRAM_DURATION.time()
    def create_connectivity_service(
        self, request : Service, grpc_context : grpc.ServicerContext) -> ServiceId:

        CREATECONNECTIVITYSERVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('create_connectivity_service request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = ServiceId()
            LOGGER.info('create_connectivity_service reply: {}'.format(str(reply)))
            CREATECONNECTIVITYSERVICE_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('create_connectivity_service exception')
            CREATECONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('create_connectivity_service exception')
            CREATECONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @EDITCONNECTIVITYSERVICE_HISTOGRAM_DURATION.time()
    def edit_connectivity_service(
        self, request : Service, grpc_context : grpc.ServicerContext) -> ServiceId:

        EDITCONNECTIVITYSERVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('edit_connectivity_service request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = ServiceId()
            LOGGER.info('edit_connectivity_service reply: {}'.format(str(reply)))
            EDITCONNECTIVITYSERVICE_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('edit_connectivity_service exception')
            EDITCONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('edit_connectivity_service exception')
            EDITCONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @DELETECONNECTIVITYSERVICE_HISTOGRAM_DURATION.time()
    def delete_connectivity_service(
        self, request : Service, grpc_context : grpc.ServicerContext) -> Empty:

        DELETECONNECTIVITYSERVICE_COUNTER_STARTED.inc()
        try:
            LOGGER.info('delete_connectivity_service request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = Empty()
            LOGGER.info('delete_connectivity_service reply: {}'.format(str(reply)))
            DELETECONNECTIVITYSERVICE_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('delete_connectivity_service exception')
            DELETECONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('delete_connectivity_service exception')
            DELETECONNECTIVITYSERVICE_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @GETALLACTIVECONNECTIVITYSERVICES_HISTOGRAM_DURATION.time()
    def get_all_active_connectivity_services(
        self, request : Empty, grpc_context : grpc.ServicerContext) -> ServiceIdList:

        GETALLACTIVECONNECTIVITYSERVICES_COUNTER_STARTED.inc()
        try:
            LOGGER.info('get_all_active_connectivity_services request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = ServiceIdList()
            LOGGER.info('get_all_active_connectivity_services reply: {}'.format(str(reply)))
            GETALLACTIVECONNECTIVITYSERVICES_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('get_all_active_connectivity_services exception')
            GETALLACTIVECONNECTIVITYSERVICES_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('get_all_active_connectivity_services exception')
            GETALLACTIVECONNECTIVITYSERVICES_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))

    @CLEARALLCONNECTIVITYSERVICES_HISTOGRAM_DURATION.time()
    def clear_all_connectivity_services(
        self, request : Empty, grpc_context : grpc.ServicerContext) -> Empty:

        CLEARALLCONNECTIVITYSERVICES_COUNTER_STARTED.inc()
        try:
            LOGGER.info('clear_all_connectivity_services request: {}'.format(str(request)))
            LOGGER.warning('NOT IMPLEMENTED')

            # ----- Validate request data and pre-conditions -----------------------------------------------------------

            # ----- Retrieve data from the database --------------------------------------------------------------------

            # ----- Compose reply --------------------------------------------------------------------------------------
            reply = Empty()
            LOGGER.info('clear_all_connectivity_services reply: {}'.format(str(reply)))
            CLEARALLCONNECTIVITYSERVICES_COUNTER_COMPLETED.inc()
            return reply
        except ServiceException as e:                               # pragma: no cover (ServiceException not thrown)
            LOGGER.exception('clear_all_connectivity_services exception')
            CLEARALLCONNECTIVITYSERVICES_COUNTER_FAILED.inc()
            grpc_context.abort(e.code, e.details)
        except Exception as e:                                      # pragma: no cover
            LOGGER.exception('clear_all_connectivity_services exception')
            CLEARALLCONNECTIVITYSERVICES_COUNTER_FAILED.inc()
            grpc_context.abort(grpc.StatusCode.INTERNAL, str(e))
