<reponame>UNakade/server
from flask import current_app

import fdrtd_server.exceptions


def get_bus():
    with current_app.app_context():
        return current_app.bus


class Bus:

    def __init__(self):
        self.microservices = {}

    def set_microservices(self, microservices):
        self.microservices = microservices

    def list_microservices(self):
        result = []
        for uuid, microservice in self.microservices.items():
            result.append({'identifiers': microservice['identifiers']})
        return result

    def select_microservice(self, requirements):

        def test(identifiers):
            for requirement in requirements:
                if requirement not in identifiers:
                    return False
                if identifiers[requirement] != requirements[requirement]:
                    return False
            return True

        for uuid, microservice in self.microservices.items():
            if test(microservice['identifiers']):
                return uuid

        raise fdrtd_server.exceptions.MicroserviceNotFound(requirements)

    def call_microservice(self, handle, function, parameters=None, callback=None, public=False):

        if handle not in self.microservices:
            raise fdrtd_server.exceptions.MicroserviceNotFound(handle)
        microservice = self.microservices[handle]

        if function in microservice['instance'].make_public():
            fn = microservice['instance'].make_public()[function]
        elif function in microservice.get('public', {}):
            fn = getattr(microservice['instance'], function)
        elif public:
            raise fdrtd_server.exceptions.FunctionNotPublic(function)
        elif hasattr(microservice['instance'], function):
            fn = getattr(microservice['instance'], function)
        else:
            raise fdrtd_server.exceptions.FunctionNotFound(function)

        if callback is None:
            result = fn() if parameters is None else fn(**parameters)
        else:
            result = fn(callback=callback) if parameters is None else fn(**parameters, callback=callback)
        return result

from flask import current_app

import fdrtd_server.exceptions


def get_bus():
    with current_app.app_context():
        return current_app.bus


class Bus:

    def __init__(self):
        self.microservices = {}

    def set_microservices(self, microservices):
        self.microservices = microservices

    def list_microservices(self):
        result = []
        for uuid, microservice in self.microservices.items():
            result.append({'identifiers': microservice['identifiers']})
        return result

    def select_microservice(self, requirements):

        def test(identifiers):
            for requirement in requirements:
                if requirement not in identifiers:
                    return False
                if identifiers[requirement] != requirements[requirement]:
                    return False
            return True

        for uuid, microservice in self.microservices.items():
            if test(microservice['identifiers']):
                return uuid

        raise fdrtd_server.exceptions.MicroserviceNotFound(requirements)

    def call_microservice(self, handle, function, parameters=None, callback=None, public=False):

        if handle not in self.microservices:
            raise fdrtd_server.exceptions.MicroserviceNotFound(handle)
        microservice = self.microservices[handle]

        if function in microservice['instance'].make_public():
            fn = microservice['instance'].make_public()[function]
        elif function in microservice.get('public', {}):
            fn = getattr(microservice['instance'], function)
        elif public:
            raise fdrtd_server.exceptions.FunctionNotPublic(function)
        elif hasattr(microservice['instance'], function):
            fn = getattr(microservice['instance'], function)
        else:
            raise fdrtd_server.exceptions.FunctionNotFound(function)

        if callback is None:
            result = fn() if parameters is None else fn(**parameters)
        else:
            result = fn(callback=callback) if parameters is None else fn(**parameters, callback=callback)
        return result