# Path: intelligine/synergy/event/move/MoveAction.py
# class MoveAction(Action):
# 
#     _listen = MoveEvent
# 
#     def __init__(self, object_id, parameters):
#         super().__init__(object_id, parameters)
#         self._move_to_point = None
#         self._move_to_direction = None
# 
#     def run(self, obj, context, synergy_manager):
#         if self._parameters.get(MoveEvent.PARAM_NEW_MODE, None):
#             obj.get_brain().switch_to_mode(self._parameters[MoveEvent.PARAM_NEW_MODE])
#             return
# 
#         try:
#             self._apply_move(obj, context)
#         except ActionAborted:
#             # TODO: Dans l'obj ces lignes
#             blocked_since = context.metas.value.get(BLOCKED_SINCE, self._object_id, allow_empty=True, empty_value=0)
#             context.metas.value.set(BLOCKED_SINCE, obj.get_id(), blocked_since+1)
# 
#     def _apply_move(self, obj, context):
#         # TODO: il ne faut pas choisir une direction 14.
#         if MoveEvent.PARAM_DIRECTION not in self._parameters or self._parameters[MoveEvent.PARAM_DIRECTION] == 14:
#             raise ActionAborted()
# 
#         obj.set_position(self._parameters[MoveEvent.PARAM_POSITION])
#         obj.set_previous_direction(self._parameters[MoveEvent.PARAM_DIRECTION])
#         obj.get_brain().get_part(BRAIN_PART_MOVE).done()
# 
# Path: intelligine/synergy/object/Food.py
# class Food(Resource):
# 
#     def __init__(self, collection, context):
#         super().__init__(collection, context)
#         context.metas.list.add(TYPE, self.get_id(), TYPE_RESOURCE_EXPLOITABLE)
# 
#     def get_what_carry(self):
#         return self  # dev
#         clone = self.__class__(self._collection, self._context)
#         self._collection.add_object(clone)
#         return clone
# 
#     def transform_to_stocked(self):
#         self._context.metas.list.remove(TYPE, self.get_id(), TYPE_RESOURCE_EXPLOITABLE)
#         self._context.metas.list.add(TYPE, self.get_id(), TYPE_RESOURCE_EATABLE)
#         self._add_col(COL_EATABLE)
#         self._add_col(COL_SMELL)
#         self._set_smell(SMELL_FOOD)
# 
# Path: intelligine/synergy/event/transport/PutableEvent.py
# class PutableEvent(NearEvent):
#     """
#     TODO: Refactorise with TakableEvent
#     """
# 
#     PARAM_PUT = 'put'
#     PARAM_PUT_TO = 'put_to'
#     PARAM_HOME_FAIL = 'home_fail'
#     _mechanism = AroundMechanism
#     _concern = COL_TRANSPORTER_CARRYING
#     _near_name = 'objects_ids_putable'
#     _near_map = lambda self, near_object_id, context: context.metas.states.have(near_object_id, TRANSPORTABLE)
# 
#     def _prepare(self, object_id, context, parameters={}):
#         if not self._can_put(object_id, context):
#             raise NotConcernedEvent()
# 
#         try:
#             self.map(context, parameters, stop_at_first=False)
#         except NearNothingFound:
#             raise NotConcernedEvent()
# 
#         brain_part = get_brain_part(context, object_id, BRAIN_PART_PUT)
#         parameters[self.PARAM_PUT] = []
#         parameters[self.PARAM_PUT_TO] = []
#         parameters[self.PARAM_HOME_FAIL] = False
# 
#         for object_near_id in parameters[self._near_name]:
#             if brain_part.can_put(context, object_id, object_near_id):
#                 try:
#                     put_position = brain_part.get_put_position(context, object_id, object_near_id)
#                     parameters[self.PARAM_PUT].append(object_near_id)
#                     parameters[self.PARAM_PUT_TO].append(put_position)
#                     return parameters  # Si a terme on veut tous les calculer a l'avance, ne pas retourner ici
#                 except CantFindWhereToPut:
#                     pass  # On continu la booucle
# 
#         # Si a terme on veut tous les calculer a l'avance, raise que si rien trouve
#         if AntMoveBrainPart._on_home_smell(context, object_id):  # TODO: Reanger code (._ acces protege)
#             parameters[self.PARAM_HOME_FAIL] = True
#         return parameters
# 
#     @staticmethod
#     def _can_put(object_id, context):
#         return not context.metas.value.get(CANT_PUT_STILL, object_id, allow_empty=True)
# 
#     @classmethod
#     def _object_can_put(cls, object_id, context, object_to_put_id):
#         object_take_brain_part = get_brain_part(context, object_id, BRAIN_PART_PUT)
#         return object_take_brain_part.can_put(context, object_id, object_to_put_id)
# 
# Path: intelligine/cst.py
# CANT_CARRY_STILL = IncrementedNamedInt.get('intelligine.cantcarry.still')
# 
# BRAIN_PART_PUT = IncrementedNamedInt.get('intelligine.brain.part.put')


from synergine.synergy.event.exception.ActionAborted import ActionAborted
from intelligine.synergy.event.move.MoveAction import MoveAction
from intelligine.synergy.object.Food import Food
from synergine.synergy.event.Action import Action
from intelligine.synergy.event.transport.PutableEvent import PutableEvent
from intelligine.cst import CANT_CARRY_STILL, BRAIN_PART_PUT


class PutableAction(Action):

    _listen = PutableEvent
    _depend = [MoveAction]

    def run(self, obj, context, synergy_manager):
        obj_transported = obj.get_carried()

        if not self._parameters[PutableEvent.PARAM_PUT_TO]:
            if self._parameters[PutableEvent.PARAM_HOME_FAIL]:
                obj.increment_put_fail_count()
            raise ActionAborted()


# Path: intelligine/synergy/event/move/MoveAction.py
# class MoveAction(Action):
# 
#     _listen = MoveEvent
# 
#     def __init__(self, object_id, parameters):
#         super().__init__(object_id, parameters)
#         self._move_to_point = None
#         self._move_to_direction = None
# 
#     def run(self, obj, context, synergy_manager):
#         if self._parameters.get(MoveEvent.PARAM_NEW_MODE, None):
#             obj.get_brain().switch_to_mode(self._parameters[MoveEvent.PARAM_NEW_MODE])
#             return
# 
#         try:
#             self._apply_move(obj, context)
#         except ActionAborted:
#             # TODO: Dans l'obj ces lignes
#             blocked_since = context.metas.value.get(BLOCKED_SINCE, self._object_id, allow_empty=True, empty_value=0)
#             context.metas.value.set(BLOCKED_SINCE, obj.get_id(), blocked_since+1)
# 
#     def _apply_move(self, obj, context):
#         # TODO: il ne faut pas choisir une direction 14.
#         if MoveEvent.PARAM_DIRECTION not in self._parameters or self._parameters[MoveEvent.PARAM_DIRECTION] == 14:
#             raise ActionAborted()
# 
#         obj.set_position(self._parameters[MoveEvent.PARAM_POSITION])
#         obj.set_previous_direction(self._parameters[MoveEvent.PARAM_DIRECTION])
#         obj.get_brain().get_part(BRAIN_PART_MOVE).done()
# 
# Path: intelligine/synergy/object/Food.py
# class Food(Resource):
# 
#     def __init__(self, collection, context):
#         super().__init__(collection, context)
#         context.metas.list.add(TYPE, self.get_id(), TYPE_RESOURCE_EXPLOITABLE)
# 
#     def get_what_carry(self):
#         return self  # dev
#         clone = self.__class__(self._collection, self._context)
#         self._collection.add_object(clone)
#         return clone
# 
#     def transform_to_stocked(self):
#         self._context.metas.list.remove(TYPE, self.get_id(), TYPE_RESOURCE_EXPLOITABLE)
#         self._context.metas.list.add(TYPE, self.get_id(), TYPE_RESOURCE_EATABLE)
#         self._add_col(COL_EATABLE)
#         self._add_col(COL_SMELL)
#         self._set_smell(SMELL_FOOD)
# 
# Path: intelligine/synergy/event/transport/PutableEvent.py
# class PutableEvent(NearEvent):
#     """
#     TODO: Refactorise with TakableEvent
#     """
# 
#     PARAM_PUT = 'put'
#     PARAM_PUT_TO = 'put_to'
#     PARAM_HOME_FAIL = 'home_fail'
#     _mechanism = AroundMechanism
#     _concern = COL_TRANSPORTER_CARRYING
#     _near_name = 'objects_ids_putable'
#     _near_map = lambda self, near_object_id, context: context.metas.states.have(near_object_id, TRANSPORTABLE)
# 
#     def _prepare(self, object_id, context, parameters={}):
#         if not self._can_put(object_id, context):
#             raise NotConcernedEvent()
# 
#         try:
#             self.map(context, parameters, stop_at_first=False)
#         except NearNothingFound:
#             raise NotConcernedEvent()
# 
#         brain_part = get_brain_part(context, object_id, BRAIN_PART_PUT)
#         parameters[self.PARAM_PUT] = []
#         parameters[self.PARAM_PUT_TO] = []
#         parameters[self.PARAM_HOME_FAIL] = False
# 
#         for object_near_id in parameters[self._near_name]:
#             if brain_part.can_put(context, object_id, object_near_id):
#                 try:
#                     put_position = brain_part.get_put_position(context, object_id, object_near_id)
#                     parameters[self.PARAM_PUT].append(object_near_id)
#                     parameters[self.PARAM_PUT_TO].append(put_position)
#                     return parameters  # Si a terme on veut tous les calculer a l'avance, ne pas retourner ici
#                 except CantFindWhereToPut:
#                     pass  # On continu la booucle
# 
#         # Si a terme on veut tous les calculer a l'avance, raise que si rien trouve
#         if AntMoveBrainPart._on_home_smell(context, object_id):  # TODO: Reanger code (._ acces protege)
#             parameters[self.PARAM_HOME_FAIL] = True
#         return parameters
# 
#     @staticmethod
#     def _can_put(object_id, context):
#         return not context.metas.value.get(CANT_PUT_STILL, object_id, allow_empty=True)
# 
#     @classmethod
#     def _object_can_put(cls, object_id, context, object_to_put_id):
#         object_take_brain_part = get_brain_part(context, object_id, BRAIN_PART_PUT)
#         return object_take_brain_part.can_put(context, object_id, object_to_put_id)
# 
# Path: intelligine/cst.py
# CANT_CARRY_STILL = IncrementedNamedInt.get('intelligine.cantcarry.still')
# 
# BRAIN_PART_PUT = IncrementedNamedInt.get('intelligine.brain.part.put')


# Path: intelligine/synergy/event/transport/PutableAction.py
from synergine.synergy.event.exception.ActionAborted import ActionAborted
from intelligine.synergy.event.move.MoveAction import MoveAction
from intelligine.synergy.object.Food import Food
from synergine.synergy.event.Action import Action
from intelligine.synergy.event.transport.PutableEvent import PutableEvent
from intelligine.cst import CANT_CARRY_STILL, BRAIN_PART_PUT



class PutableAction(Action):

    _listen = PutableEvent
    _depend = [MoveAction]

    def run(self, obj, context, synergy_manager):
        obj_transported = obj.get_carried()

        if not self._parameters[PutableEvent.PARAM_PUT_TO]:
            if self._parameters[PutableEvent.PARAM_HOME_FAIL]:
                obj.increment_put_fail_count()
            raise ActionAborted()


        for position_to_put in self._parameters[PutableEvent.PARAM_PUT_TO]: