import numpy as np

from src.gameplay.core.middlewares.battleList import setBattleListMiddleware


def test_empty_battle_list_is_not_attacking(mocker):
    mocker.patch('src.gameplay.core.middlewares.battleList.getContent', return_value=None)
    mocker.patch('src.gameplay.core.middlewares.battleList.getCreatures', return_value=[])
    attacking = mocker.patch('src.gameplay.core.middlewares.battleList.isAttackingSomeCreature')
    context = {
        'ng_screenshot': object(),
        'ng_battleList': {'creatures': None},
        'ng_cave': {'isAttackingSomeCreature': True},
    }

    assert setBattleListMiddleware(context) is context
    assert context['ng_battleList']['creatures'] == []
    assert context['ng_cave']['isAttackingSomeCreature'] is False
    attacking.assert_not_called()


def test_numpy_battle_list_can_be_checked(mocker):
    creatures = np.array([[1, 2], [3, 4]])
    mocker.patch('src.gameplay.core.middlewares.battleList.getContent', return_value=None)
    mocker.patch('src.gameplay.core.middlewares.battleList.getCreatures', return_value=creatures)
    attacking = mocker.patch(
        'src.gameplay.core.middlewares.battleList.isAttackingSomeCreature',
        return_value=True,
    )
    context = {
        'ng_screenshot': object(),
        'ng_battleList': {'creatures': None},
        'ng_cave': {'isAttackingSomeCreature': False},
    }

    assert setBattleListMiddleware(context) is context
    assert context['ng_battleList']['creatures'] is creatures
    assert context['ng_cave']['isAttackingSomeCreature'] is True
    attacking.assert_called_once_with(creatures)


def _ksContext(players, previousHp):
    return {
        'ng_screenshot': object(),
        'ng_battleList': {'creatures': None, 'previousCreaturesHp': previousHp},
        'ng_cave': {'isAttackingSomeCreature': False},
        'gameWindow': {'players': players},
        'ng_targeting': {},
    }


def _mockBattleListRow(mocker, name, hp, isBeingAttacked=False):
    mocker.patch(
        'src.gameplay.core.middlewares.battleList.getContent',
        return_value=np.zeros((22, 156), dtype=np.uint8))
    mocker.patch(
        'src.gameplay.core.middlewares.battleList.getCreatures',
        return_value=[{'name': name, 'isBeingAttacked': isBeingAttacked}])
    mocker.patch(
        'src.gameplay.core.middlewares.battleList.isAttackingSomeCreature',
        return_value=isBeingAttacked)
    mocker.patch(
        'src.gameplay.core.middlewares.battleList.getFilledSlotsCount',
        return_value=1)
    mocker.patch(
        'src.gameplay.core.middlewares.battleList.getCreaturesHpPercentages',
        return_value=[hp])


def test_hp_drop_by_other_player_marks_killsteal(mocker):
    _mockBattleListRow(mocker, 'wasp', 40)
    ignoreSpy = mocker.patch(
        'src.gameplay.core.middlewares.battleList.ignoreCreatureTemporarily')
    context = _ksContext(['Some Player'], {'wasp': 80})

    setBattleListMiddleware(context)

    ignoreSpy.assert_called_once_with(context, 'wasp')
    assert context['ng_battleList']['creaturesHp'] == {'wasp': 40}
    assert context['ng_battleList']['previousCreaturesHp'] == {'wasp': 40}


def test_hp_drop_without_players_is_no_killsteal(mocker):
    _mockBattleListRow(mocker, 'wasp', 40)
    ignoreSpy = mocker.patch(
        'src.gameplay.core.middlewares.battleList.ignoreCreatureTemporarily')

    setBattleListMiddleware(_ksContext([], {'wasp': 80}))

    ignoreSpy.assert_not_called()


def test_hp_drop_on_own_target_is_no_killsteal(mocker):
    _mockBattleListRow(mocker, 'wasp', 40, isBeingAttacked=True)
    ignoreSpy = mocker.patch(
        'src.gameplay.core.middlewares.battleList.ignoreCreatureTemporarily')

    setBattleListMiddleware(_ksContext(['Some Player'], {'wasp': 80}))

    ignoreSpy.assert_not_called()
