import asyncio
from unittest import TestCase

from simulation.location import Location
from simulation.interactables.pickups import InvulnerabilityPickup

from .mock_world import MockWorld


class TestInvulnerabilityPickupsAndEffects(TestCase):
    def setUp(self):
        """
        Mock a game for each test individually. MockWorld() will set up a:
        avatar manager, game state, turn manager and a map generator.
        """
        self.game = MockWorld()
        self.game.simulation_runner.add_avatar(1, Location(0, 0))
        self.cell = self.game.game_state.world_map.get_cell(Location(1, 0))

    def test_invulnerability_pickups_increase_resistance_of_avatar(self):
        """
        Avatar spawns at the origin (0,0) and should have a resistance of 0. Moves
        EAST to (1,0) and should automatically pick up the pickup and get the
        effect.
        """
        self.cell.interactable = InvulnerabilityPickup(self.cell)
        self.assertEqual(self.game.avatar_manager.get_avatar(1).resistance, 0)
        self.assertEqual(
            self.cell.interactable.serialize(),
            {
                "type": "invulnerability",
                "location": {"x": self.cell.location.x, "y": self.cell.location.y},
            },
        )

        loop = asyncio.get_event_loop()
        loop.run_until_complete(
            self.game.simulation_runner.run_single_turn(
                self.game.avatar_manager.get_player_id_to_serialized_action()
            )
        )

        self.assertEqual(self.cell.avatar, self.game.avatar_manager.get_avatar(1))
        self.assertEqual(self.cell.avatar.resistance, 1000)
        self.assertEqual(len(self.cell.avatar.effects), 1)

    def test_invulnerability_pickups_can_increase_resistance_to_2000(self):
        """
        Checks if the pickup can be applied twice. First moved from ORIGIN to 1,0 ->
        then picks up the pickup, and moves to 2,0 to do the same.
        """
        loop = asyncio.get_event_loop()
        self.cell.interactable = InvulnerabilityPickup(self.cell)
        loop.run_until_complete(
            self.game.simulation_runner.run_single_turn(
                self.game.avatar_manager.get_player_id_to_serialized_action()
            )
        )
        self.assertEqual(self.cell.avatar, self.game.avatar_manager.get_avatar(1))
        self.assertEqual(self.cell.avatar.resistance, 1000)

        self.cell = self.game.game_state.world_map.get_cell(Location(2, 0))
        self.cell.interactable = InvulnerabilityPickup(self.cell)
        loop.run_until_complete(
            self.game.simulation_runner.run_single_turn(
                self.game.avatar_manager.get_player_id_to_serialized_action()
            )
        )

        self.assertEqual(self.cell.avatar.resistance, 2000)
        self.assertEqual(self.cell.avatar, self.game.avatar_manager.get_avatar(1))
