# Path: intelligine/synergy/event/move/MoveEvent.py
# class MoveEvent(Event):
# 
#     PARAM_POSITION = 'pos'
#     PARAM_DIRECTION = 'dir'
#     PARAM_NEW_MODE = 'mod'
# 
#     _mechanism = Mechanism
#     _concern = COL_WALKER
# 
#     def _prepare(self, object_id, context, parameters={}):
#         try:
#             direction = self._get_direction(object_id, context)
#         except UnableToFoundMovement:
#             raise NotConcernedEvent()
#         except MovementModeExpired as movement_expired:
#             parameters[self.PARAM_NEW_MODE] = movement_expired.get_switch_to_mode()
#             return parameters
# 
#         object_point = context.metas.value.get(POSITION, object_id)
#         move_to_point = get_position_with_direction_decal(direction, object_point)
#         # TODO: future: c le brain qui calcule ou aller, et donc si c possible
#         if self._direction_point_is_possible(context, move_to_point):
#             parameters[self.PARAM_POSITION] = move_to_point
#             parameters[self.PARAM_DIRECTION] = direction
#         # TODO: Sinon lever un NotConcernedEvent
#         return parameters
# 
#     def _get_direction(self, object_id, context):
#         object_move_brain_part = get_brain_part(context, object_id, BRAIN_PART_MOVE)
#         return object_move_brain_part.get_direction(context, object_id)
# 
#     @staticmethod
#     def _direction_point_is_possible(context, direction_point):
#         return context.position_is_penetrable(direction_point)
# 
# Path: intelligine/cst.py
# BRAIN_PART_MOVE = IncrementedNamedInt.get('intelligine.brain.part.move')


from synergine.synergy.event.Action import Action
from intelligine.synergy.event.move.MoveEvent import MoveEvent
from synergine.synergy.event.exception.ActionAborted import ActionAborted
from intelligine.cst import BRAIN_PART_MOVE
from synergine_xyz.cst import BLOCKED_SINCE


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()


# Path: intelligine/synergy/event/move/MoveEvent.py
# class MoveEvent(Event):
# 
#     PARAM_POSITION = 'pos'
#     PARAM_DIRECTION = 'dir'
#     PARAM_NEW_MODE = 'mod'
# 
#     _mechanism = Mechanism
#     _concern = COL_WALKER
# 
#     def _prepare(self, object_id, context, parameters={}):
#         try:
#             direction = self._get_direction(object_id, context)
#         except UnableToFoundMovement:
#             raise NotConcernedEvent()
#         except MovementModeExpired as movement_expired:
#             parameters[self.PARAM_NEW_MODE] = movement_expired.get_switch_to_mode()
#             return parameters
# 
#         object_point = context.metas.value.get(POSITION, object_id)
#         move_to_point = get_position_with_direction_decal(direction, object_point)
#         # TODO: future: c le brain qui calcule ou aller, et donc si c possible
#         if self._direction_point_is_possible(context, move_to_point):
#             parameters[self.PARAM_POSITION] = move_to_point
#             parameters[self.PARAM_DIRECTION] = direction
#         # TODO: Sinon lever un NotConcernedEvent
#         return parameters
# 
#     def _get_direction(self, object_id, context):
#         object_move_brain_part = get_brain_part(context, object_id, BRAIN_PART_MOVE)
#         return object_move_brain_part.get_direction(context, object_id)
# 
#     @staticmethod
#     def _direction_point_is_possible(context, direction_point):
#         return context.position_is_penetrable(direction_point)
# 
# Path: intelligine/cst.py
# BRAIN_PART_MOVE = IncrementedNamedInt.get('intelligine.brain.part.move')


# Path: intelligine/synergy/event/move/MoveAction.py
from synergine.synergy.event.Action import Action
from intelligine.synergy.event.move.MoveEvent import MoveEvent
from synergine.synergy.event.exception.ActionAborted import ActionAborted
from intelligine.cst import BRAIN_PART_MOVE
from synergine_xyz.cst import BLOCKED_SINCE



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])