# Path: intelligine/core/exceptions.py
# class UnableToFoundMovement(MovementException):
#     pass
# 
# class MovementModeExpired(MovementException):
# 
#     def __init__(self, *args, mode, **kwargs):
#         super().__init__(*args, **kwargs)
#         self._switch_to_mode = mode
# 
#     def get_switch_to_mode(self):
#         return self._switch_to_mode
# 
# Path: intelligine/synergy/event/move/direction.py
# def get_position_with_direction_decal(direction=CENTER, point=(0, 0, 0)):
#     z, x, y = point
#     directions_modifier = directions_modifiers[direction]
#     return z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2]
# 
# Path: intelligine/shorcut/brain.py
# def get_brain_part(context, object_id, brain_part_name):
#     object_class = context.metas.value.get(INSTANCE_CLASS, object_id)
#     object_brain_schema = context.metas.value.get(BRAIN_SCHEMA, object_class)
#     return object_brain_schema[brain_part_name]
# 
# Path: intelligine/synergy/event/Event.py
# class Event(BaseEvent):
#     pass
# 
# Path: intelligine/cst.py
# COL_WALKER = IncrementedNamedInt.get('intelligine.col.walker')
# 
# BRAIN_SCHEMA = IncrementedNamedInt.get('intelligine.brain_schema')
# 
# BRAIN_PART_MOVE = IncrementedNamedInt.get('intelligine.brain.part.move')


from intelligine.core.exceptions import UnableToFoundMovement, MovementModeExpired
from intelligine.synergy.event.move.direction import get_position_with_direction_decal
from intelligine.shorcut.brain import get_brain_part
from synergine.core.exceptions import NotConcernedEvent
from intelligine.synergy.event.Event import Event
from synergine.core.simulation.mechanism.Mechanism import Mechanism
from intelligine.cst import COL_WALKER, BRAIN_SCHEMA, BRAIN_PART_MOVE
from synergine_xyz.cst import POSITION

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)

# Path: intelligine/core/exceptions.py
# class UnableToFoundMovement(MovementException):
#     pass
# 
# class MovementModeExpired(MovementException):
# 
#     def __init__(self, *args, mode, **kwargs):
#         super().__init__(*args, **kwargs)
#         self._switch_to_mode = mode
# 
#     def get_switch_to_mode(self):
#         return self._switch_to_mode
# 
# Path: intelligine/synergy/event/move/direction.py
# def get_position_with_direction_decal(direction=CENTER, point=(0, 0, 0)):
#     z, x, y = point
#     directions_modifier = directions_modifiers[direction]
#     return z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2]
# 
# Path: intelligine/shorcut/brain.py
# def get_brain_part(context, object_id, brain_part_name):
#     object_class = context.metas.value.get(INSTANCE_CLASS, object_id)
#     object_brain_schema = context.metas.value.get(BRAIN_SCHEMA, object_class)
#     return object_brain_schema[brain_part_name]
# 
# Path: intelligine/synergy/event/Event.py
# class Event(BaseEvent):
#     pass
# 
# Path: intelligine/cst.py
# COL_WALKER = IncrementedNamedInt.get('intelligine.col.walker')
# 
# BRAIN_SCHEMA = IncrementedNamedInt.get('intelligine.brain_schema')
# 
# BRAIN_PART_MOVE = IncrementedNamedInt.get('intelligine.brain.part.move')


# Path: intelligine/synergy/event/move/MoveEvent.py
from intelligine.core.exceptions import UnableToFoundMovement, MovementModeExpired
from intelligine.synergy.event.move.direction import get_position_with_direction_decal
from intelligine.shorcut.brain import get_brain_part
from synergine.core.exceptions import NotConcernedEvent
from intelligine.synergy.event.Event import Event
from synergine.core.simulation.mechanism.Mechanism import Mechanism
from intelligine.cst import COL_WALKER, BRAIN_SCHEMA, BRAIN_PART_MOVE
from synergine_xyz.cst import POSITION


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)