# Path: intelligine/core/exceptions.py
# class BestMoleculeHere(MoleculeException):
# 
#     def __init__(self, best_distance,  *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self._best_distance = best_distance
# 
#     def get_best_distance(self):
#         return self._best_distance
# 
# class NoMolecule(MoleculeException):
#     pass
# 
# Path: intelligine/cst.py
# MOLECULES_INFOS = IncrementedNamedInt.get('intelligine.mol.infos')
# 
# Path: intelligine/simulation/molecule/MoleculeFlavour.py
# class MoleculeFlavour():
# 
#     @classmethod
#     def new_from_raw_data(cls, raw_data):
#         flavour = {}
#         for category in raw_data:
#             molecules_by_category = raw_data[category]
#             for type in molecules_by_category:
#                 distance, intensity, cycle_age = molecules_by_category[type]
#                 if category not in flavour:
#                     flavour[category] = {}
#                 flavour[category][type] = Molecule(category, type, distance, intensity, cycle_age)
#         return cls(flavour)
# 
#     def get_raw_data(self):
#         raw_data = {}
#         for category in self._flavour:
#             molecules_by_category = self._flavour[category]
#             for type in molecules_by_category:
#                 molecule = molecules_by_category[type]
#                 if category not in raw_data:
#                     raw_data[category] = {}
#                 if molecule.get_intensity() >= 0:
#                     raw_data[category][type] = (molecule.get_distance(),
#                                                 molecule.get_intensity(),
#                                                 molecule.get_cycle_age())
#         return raw_data
# 
#     def __init__(self, flavour):
#         self._flavour = flavour
# 
#     def get_molecule(self, category, type):
#         types = self.get_types(category)
#         if type not in types:
#             raise NoTypeInMolecule()
#         return types[type]
# 
#     def get_molecules(self, category):
#         """
# 
#         :param category:
#         :return: Molecules dict or empty dict of no molecules
#         """
#         try:
#             return self.get_types(category).values()
#         except NoCategoryInMolecule:
#             return {}
# 
#     def get_molecules_types(self, category):
#         try:
#             return self.get_types(category).keys()
#         except NoCategoryInMolecule:
#             return {}
# 
#     def get_types(self, category):
#         if category not in self._flavour:
#             raise NoCategoryInMolecule()
#         return self._flavour[category]
# 
#     def set_molecule(self, molecule):
#         category = molecule.get_category()
#         type = molecule.get_type()
# 
#         if category not in self._flavour:
#             self._flavour[category] = {}
# 
#         self._flavour[category][type] = molecule
# 
#     def remove_molecule(self, molecule):
#         category = molecule.get_category()
#         type = molecule.get_type()
#         del(self._flavour[category][type])
# 
# Path: intelligine/simulation/molecule/Molecule.py
# class Molecule():
# 
#     def __init__(self, category, type, distance=None, intensity=0, cycle_age=None):
#         self._category = category
#         self._type = type
#         self._distance = distance
#         self._intensity = intensity
#         self._cycle_age = cycle_age
# 
#     def get_category(self):
#         return self._category
# 
#     def get_type(self):
#         return self._type
# 
#     def get_distance(self):
#         return self._distance
# 
#     def set_distance(self, distance):
#         self._distance = distance
# 
#     def get_intensity(self):
#         return self._intensity
# 
#     def get_cycle_age(self):
#         return self._cycle_age
# 
#     def set_cycle_age(self, cycle_age):
#         self._cycle_age = cycle_age
# 
#     def increment_intensity(self, increment_value):
#         self._intensity += increment_value


from intelligine.core.exceptions import BestMoleculeHere, NoMolecule
from intelligine.cst import MOLECULES_INFOS
from intelligine.simulation.molecule.MoleculeFlavour import MoleculeFlavour
from intelligine.simulation.molecule.Molecule import Molecule


class MoleculesManager():

    def __init__(self, context):
        self._context = context

    def get_flavour(self, position):
        point_molecules = self._context.metas.value.get(MOLECULES_INFOS,
                                                        position,
                                                        allow_empty=True,
                                                        empty_value={})
        return MoleculeFlavour.new_from_raw_data(point_molecules)

    def set_flavour(self, position, flavour):
        self._context.metas.value.set(MOLECULES_INFOS, position, flavour.get_raw_data())

    def get_molecule(self, position, category, type, allow_empty=False):
        flavour = self.get_flavour(position)
        try:
            return flavour.get_molecule(category, type)
        except NoMolecule:
            if allow_empty:
                return Molecule()
            raise

    def increment_with_molecule(self, position, apposed_molecule, cycle_age):
        flavour = self.get_flavour(position)
        try:
            position_molecule = flavour.get_molecule(apposed_molecule.get_category(), apposed_molecule.get_type())

# Path: intelligine/core/exceptions.py
# class BestMoleculeHere(MoleculeException):
# 
#     def __init__(self, best_distance,  *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self._best_distance = best_distance
# 
#     def get_best_distance(self):
#         return self._best_distance
# 
# class NoMolecule(MoleculeException):
#     pass
# 
# Path: intelligine/cst.py
# MOLECULES_INFOS = IncrementedNamedInt.get('intelligine.mol.infos')
# 
# Path: intelligine/simulation/molecule/MoleculeFlavour.py
# class MoleculeFlavour():
# 
#     @classmethod
#     def new_from_raw_data(cls, raw_data):
#         flavour = {}
#         for category in raw_data:
#             molecules_by_category = raw_data[category]
#             for type in molecules_by_category:
#                 distance, intensity, cycle_age = molecules_by_category[type]
#                 if category not in flavour:
#                     flavour[category] = {}
#                 flavour[category][type] = Molecule(category, type, distance, intensity, cycle_age)
#         return cls(flavour)
# 
#     def get_raw_data(self):
#         raw_data = {}
#         for category in self._flavour:
#             molecules_by_category = self._flavour[category]
#             for type in molecules_by_category:
#                 molecule = molecules_by_category[type]
#                 if category not in raw_data:
#                     raw_data[category] = {}
#                 if molecule.get_intensity() >= 0:
#                     raw_data[category][type] = (molecule.get_distance(),
#                                                 molecule.get_intensity(),
#                                                 molecule.get_cycle_age())
#         return raw_data
# 
#     def __init__(self, flavour):
#         self._flavour = flavour
# 
#     def get_molecule(self, category, type):
#         types = self.get_types(category)
#         if type not in types:
#             raise NoTypeInMolecule()
#         return types[type]
# 
#     def get_molecules(self, category):
#         """
# 
#         :param category:
#         :return: Molecules dict or empty dict of no molecules
#         """
#         try:
#             return self.get_types(category).values()
#         except NoCategoryInMolecule:
#             return {}
# 
#     def get_molecules_types(self, category):
#         try:
#             return self.get_types(category).keys()
#         except NoCategoryInMolecule:
#             return {}
# 
#     def get_types(self, category):
#         if category not in self._flavour:
#             raise NoCategoryInMolecule()
#         return self._flavour[category]
# 
#     def set_molecule(self, molecule):
#         category = molecule.get_category()
#         type = molecule.get_type()
# 
#         if category not in self._flavour:
#             self._flavour[category] = {}
# 
#         self._flavour[category][type] = molecule
# 
#     def remove_molecule(self, molecule):
#         category = molecule.get_category()
#         type = molecule.get_type()
#         del(self._flavour[category][type])
# 
# Path: intelligine/simulation/molecule/Molecule.py
# class Molecule():
# 
#     def __init__(self, category, type, distance=None, intensity=0, cycle_age=None):
#         self._category = category
#         self._type = type
#         self._distance = distance
#         self._intensity = intensity
#         self._cycle_age = cycle_age
# 
#     def get_category(self):
#         return self._category
# 
#     def get_type(self):
#         return self._type
# 
#     def get_distance(self):
#         return self._distance
# 
#     def set_distance(self, distance):
#         self._distance = distance
# 
#     def get_intensity(self):
#         return self._intensity
# 
#     def get_cycle_age(self):
#         return self._cycle_age
# 
#     def set_cycle_age(self, cycle_age):
#         self._cycle_age = cycle_age
# 
#     def increment_intensity(self, increment_value):
#         self._intensity += increment_value


# Path: intelligine/synergy/stigmergy/MoleculesManager.py
from intelligine.core.exceptions import BestMoleculeHere, NoMolecule
from intelligine.cst import MOLECULES_INFOS
from intelligine.simulation.molecule.MoleculeFlavour import MoleculeFlavour
from intelligine.simulation.molecule.Molecule import Molecule



class MoleculesManager():

    def __init__(self, context):
        self._context = context

    def get_flavour(self, position):
        point_molecules = self._context.metas.value.get(MOLECULES_INFOS,
                                                        position,
                                                        allow_empty=True,
                                                        empty_value={})
        return MoleculeFlavour.new_from_raw_data(point_molecules)

    def set_flavour(self, position, flavour):
        self._context.metas.value.set(MOLECULES_INFOS, position, flavour.get_raw_data())

    def get_molecule(self, position, category, type, allow_empty=False):
        flavour = self.get_flavour(position)
        try:
            return flavour.get_molecule(category, type)
        except NoMolecule:
            if allow_empty:
                return Molecule()
            raise

    def increment_with_molecule(self, position, apposed_molecule, cycle_age):
        flavour = self.get_flavour(position)
        try:
            position_molecule = flavour.get_molecule(apposed_molecule.get_category(), apposed_molecule.get_type())

        except NoMolecule: