from xml.etree.ElementTree import tostring, fromstring

from pymasep.common import Characteristic, Agent, Intention, BaseObject, Object, State, ObjectState, Action
from test.unit.mocks.controller_mock import ControllerMock
from test.unit.mocks.game_mock import GameMock


def test_init(mock_environment):
    expected_name = 'AgentName1'
    ag = Agent(environment=mock_environment,
               name=expected_name,
               template=mock_environment.game.templates['DefaultAgentTemplate'])
    assert isinstance(ag, BaseObject)
    assert isinstance(ag, Object)
    assert isinstance(ag, Agent)
    assert expected_name == ag.name
    assert ag.action is None
    assert ag.observation is None
    assert ag.intention is None
    assert ag.reward is None


def test_choose_action(mock_environment):
    observation = State(environment=mock_environment,
                        name='state',
                        template=mock_environment.game.templates['DefaultStateTemplate'])
    expected_action_type = GameMock.ACTION_TYPE_2
    ag = Agent(environment=mock_environment,
               name='AgentName1',
               template=mock_environment.game.templates['DefaultAgentTemplate'])
    ag.controller = ControllerMock(mock_environment)
    ag.observation = observation

    ag.choose_action()

    assert expected_action_type == ag.action.type


def test_to_xml_transformed(mock_environment):
    expected_xml_str = '<Agent name="agent1" state="init" ' \
                       'controller="test.unit.mocks.controller_mock.ControllerMock" control="interface">' \
                       '<ObjectState name="state" state="init">' \
                       '<Characteristic name="CharacInt" state="init"><int /></Characteristic>' \
                       '<Characteristic name="CharacStr" state="init"><str /></Characteristic>' \
                       '<Characteristic name="Step0" state="run"><int>0</int></Characteristic>' \
                       '</ObjectState>' \
                       '<Intention name="intention" state="run">' \
                       '<Action type="1" />' \
                       '</Intention>' \
                       '</Agent>'
    ag = Agent(environment=mock_environment,
               name='agent1',
               template=mock_environment.game.templates['DefaultAgentTemplate'])
    ag.controller = ControllerMock(mock_environment)
    ag.object_state.characteristics['CharacInt'].state = 'init'
    ag.object_state.characteristics['CharacStr'].state = 'init'
    charac = Characteristic(environment=mock_environment, name='Step0',
                            template=mock_environment.game.templates['CharacInt'],
                            parent=ag.object_state)
    charac.value = 0
    ag.object_state.add_characteristic(charac)
    ag.control = 'interface'
    ag.intention = Intention(environment=mock_environment,
                             name="intention",
                             template=mock_environment.game.templates['EmptyIntentionTemplate'])
    ag.intention.add_intention(Action(environment=mock_environment,
                                      action_type=mock_environment.game.ACTION_TYPE_1))
    xml_str_result = tostring(ag.to_xml(), encoding='unicode')
    assert xml_str_result == expected_xml_str


def test_from_xml(mock_environment):
    agent_xml_str = '<Agent name="agent1" controller="test.mocks.controller_mock.ControllerMock">' \
                    '<ObjectState name="state">' \
                    '<Characteristic name="Step0"><int>0</int></Characteristic>' \
                    '</ObjectState>' \
                    '<Intention name="intention">' \
                    '<Action type="1" />' \
                    '</Intention>' \
                    '</Agent>'
    xml_node = fromstring(agent_xml_str)
    ag = mock_environment.create_base_object(name='', xml_node=xml_node)

    ag.from_xml(environment=mock_environment, xml_node=xml_node)

    assert isinstance(ag, Agent)
    assert ag.name == 'agent1'
    assert isinstance(ag.object_state, ObjectState)
    assert isinstance(ag.object_state.characteristics['Step0'], Characteristic)
    assert len(ag.intention.intentions) == 1
    assert isinstance(ag.intention.intentions[0], Action)
    assert ag.intention.intentions[0].type == 1


def test_from_xml_control_interface(mock_environment):
    agent_xml_str = '<Agent name="agent1" control="interface">' \
                    '<ObjectState name="state">' \
                    '<Characteristic name="Step0"><int>0</int></Characteristic>' \
                    '</ObjectState>' \
                    '</Agent>'
    xml_node = fromstring(agent_xml_str)
    ag = mock_environment.create_base_object(name='', xml_node=xml_node)

    ag.from_xml(environment=mock_environment, xml_node=xml_node)

    assert ag.control == 'interface'


def test_id_str(mock_environment):
    agent_xml_str = '<Agent name="agent1" controller="test.mocks.controller_mock.ControllerMock">' \
                    '<ObjectState name="state">' \
                    '<Characteristic name="Step0"><int>0</int></Characteristic>' \
                    '</ObjectState>' \
                    '<Intention name="intention">' \
                    '<Action type="1" />' \
                    '</Intention>' \
                    '</Agent>'
    xml_node = fromstring(agent_xml_str)
    ag = mock_environment.create_base_object(name='', xml_node=xml_node)
    ag.from_xml(environment=mock_environment, xml_node=xml_node)

    id_str = ag.id_str()

    assert id_str == 'agent1stateStep00intentionaction1'
