from xml.etree import ElementTree

from pymasep.common import State, Agent, Controller
from pymasep.communication import Message


class ExternalController(Controller):
    """
    External controller to receive action from an interface (local or remote)

    :param environment: environment for the controller
    """

    def __init__(self, environment):
        super().__init__(environment)
        self.engine = None

    def action_choice(self, observation: State, agent: Agent):
        """
        Choose the action. Get it from the action message in the current_event of the engine.
        Act only if is the turn of the agent that send the action message.

        :param observation: the observation used to choose the action.
        :param agent: the agent who choose the action.
        :return: the action chosen for the agent.
        """
        result = None
        msg_action = self.engine.current_event
        if msg_action is not None:
            if msg_action.msg_type == Message.MESSAGE_TYPE_ACTION:
                action = self.environment.create_action(xml_node=msg_action.params['action'])
                if (observation and
                        self.engine.environment.game.get_system_value(observation,
                                                                      'AgentOrder').head == agent.get_fullname() and
                        msg_action.src_sub_app_id == self.engine.get_connected_id_from_agent_fname(
                            agent.get_fullname())):
                    self.engine.logger.info(
                        'Action received ' + str(ElementTree.tostring(msg_action.params['action'])))
                    result = action
                    self.engine.current_event = None
                else:
                    self.engine.logger.debug('No action selected for turn'
                                             + self.engine.environment.game.get_system_value(observation,
                                                                                             'AgentOrder').head
                                             + ' '
                                             + str(observation))
            else:
                self.engine.logger.info('msg received is not an action : ' + str(msg_action.msg_type))
        else:
            self.engine.logger.info('No action received')
        return result
