import grpc
from common.database.api.Database import Database
from common.database.api.context.topology.device.Device import Device
from common.database.api.context.topology.device.Endpoint import Endpoint
from common.exceptions.ServiceException import ServiceException

def check_device_exists(database : Database, context_id : str, topology_id : str, device_id : str) -> Device:
    db_context = database.context(context_id).create()
    db_topology = db_context.topology(topology_id).create()
    if db_topology.devices.contains(device_id): return db_topology.device(device_id)
    msg = 'Context({})/Topology({})/Device({}) does not exist in the database.'
    msg = msg.format(context_id, topology_id, device_id)
    raise ServiceException(grpc.StatusCode.NOT_FOUND, msg)

def check_device_not_exists(database : Database, context_id : str, topology_id : str, device_id : str):
    db_context = database.context(context_id).create()
    db_topology = db_context.topology(topology_id).create()
    if not db_topology.devices.contains(device_id): return
    msg = 'Context({})/Topology({})/Device({}) already exists in the database.'
    msg = msg.format(context_id, topology_id, device_id)
    raise ServiceException(grpc.StatusCode.ALREADY_EXISTS, msg)

def check_device_endpoint_exists(
    database : Database, parent_name : str,
    context_id : str, topology_id : str, device_id : str, port_id : str) -> Endpoint:

    # Implicit validation: parent.context == endpoint.context, and parent.context created automatically
    if not database.contexts.contains(context_id):          # pragma: no cover
        msg = 'Context({}) in {} does not exist in the database.'
        msg = msg.format(context_id, parent_name)
        raise ServiceException(grpc.StatusCode.NOT_FOUND, msg)
    db_context = database.context(context_id)

    if not db_context.topologies.contains(topology_id):
        msg = 'Context({})/Topology({}) in {} does not exist in the database.'
        msg = msg.format(context_id, topology_id, parent_name)
        raise ServiceException(grpc.StatusCode.NOT_FOUND, msg)
    db_topology = db_context.topology(topology_id)

    if not db_topology.devices.contains(device_id):
        msg = 'Context({})/Topology({})/Device({}) in {} does not exist in the database.'
        msg = msg.format(context_id, topology_id, device_id, parent_name)
        raise ServiceException(grpc.StatusCode.NOT_FOUND, msg)
    db_device = db_topology.device(device_id)

    if not db_device.endpoints.contains(port_id):
        msg = 'Context({})/Topology({})/Device({})/Port({}) in {} does not exist in the database.'
        msg = msg.format(context_id, topology_id, device_id, port_id, parent_name)
        raise ServiceException(grpc.StatusCode.NOT_FOUND, msg)

    return db_device.endpoint(port_id)