import asyncio

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

from .mock_world import MockWorld


class TestInvulnerabilityPickupsAndEffects:
    def setup_method(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))

    async def test_invulnerability_pickups_increase_resistance_of_avatar(self, loop):
        """
        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)
        assert self.game.avatar_manager.get_avatar(1).resistance == 0
        assert self.cell.interactable.serialize() == {
            "type": "invulnerability",
            "location": {"x": self.cell.location.x, "y": self.cell.location.y},
        }

        await self.game.simulation_runner.run_single_turn(
            self.game.avatar_manager.get_player_id_to_serialized_action()
        )

        assert self.cell.avatar == self.game.avatar_manager.get_avatar(1)
        assert self.cell.avatar.resistance == 1000
        assert len(self.cell.avatar.effects) == 1

    async def test_invulnerability_pickups_can_increase_resistance_to_2000(self, loop):
        """
        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.
        """
        self.cell.interactable = InvulnerabilityPickup(self.cell)
        await self.game.simulation_runner.run_single_turn(
            self.game.avatar_manager.get_player_id_to_serialized_action()
        )
        assert self.cell.avatar == self.game.avatar_manager.get_avatar(1)
        assert self.cell.avatar.resistance == 1000

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

        assert self.cell.avatar.resistance == 2000
        assert self.cell.avatar == self.game.avatar_manager.get_avatar(1)
