from src.gameplay.core.tasks.walk import WalkTask


def test_walk_never_invents_coordinate(mocker):
    press = mocker.patch('src.gameplay.core.tasks.walk.press')
    mocker.patch(
        'src.gameplay.core.tasks.walk.getDirectionBetweenCoordinates',
        return_value='right',
    )
    task = WalkTask.__new__(WalkTask)
    task.walkpoint = [32348, 32227, 7]
    task.parentTask = None
    context = {
        'ng_lastPressedKey': None,
        'ng_radar': {
            'coordinate': [32347, 32227, 7],
            'previousCoordinate': [32347, 32227, 7],
        },
    }

    result = task.do(context)

    press.assert_called_once_with('right')
    assert result['ng_radar']['coordinate'] == [32347, 32227, 7]
    assert result['ng_radar']['previousCoordinate'] == [32347, 32227, 7]


def test_first_walk_is_not_skipped():
    task = WalkTask.__new__(WalkTask)
    task.walkpoint = [32348, 32227, 7]
    context = {
        'ng_radar': {
            'coordinate': [32347, 32227, 7],
            'lastCoordinateVisited': None,
        },
    }

    assert task.shouldIgnore(context) is False


def test_walk_timeout_does_not_complete_whole_waypoint(mocker):
    mocker.patch('src.gameplay.core.tasks.walk.getSpeed', return_value=220)
    mocker.patch('src.gameplay.core.tasks.walk.getTileFrictionByCoordinate', return_value=100)
    mocker.patch('src.gameplay.core.tasks.walk.getBreakpointTileMovementSpeed', return_value=200)
    context = {'ng_screenshot': object()}

    task = WalkTask(context, [32348, 32227, 7])

    assert task.shouldTimeoutTreeWhenTimeout is False
    assert task.delayOfTimeout == 1.0


def test_walk_timeout_blocks_failed_tile_for_parent(mocker):
    release = mocker.patch(
        'src.gameplay.core.tasks.walk.releaseKeys',
        side_effect=lambda context: context,
    )
    parent = mocker.Mock()
    task = WalkTask.__new__(WalkTask)
    task.parentTask = parent
    task.walkpoint = [32372, 32222, 7]
    context = {'ng_radar': {'coordinate': [32372, 32223, 7]}}

    assert task.onTimeout(context) is context
    parent.blockWalkpoint.assert_called_once_with([32372, 32222, 7])
    release.assert_called_once_with(context)


def test_walk_timeout_attacks_creature_on_failed_tile(mocker):
    mocker.patch(
        'src.gameplay.core.tasks.walk.releaseKeys',
        side_effect=lambda context: context,
    )
    attack = mocker.patch('src.gameplay.core.tasks.walk.mouse.attackClick')
    parent = mocker.Mock()
    task = WalkTask.__new__(WalkTask)
    task.parentTask = parent
    task.walkpoint = [32393, 32234, 7]
    context = {
        'ng_radar': {'coordinate': [32394, 32234, 7]},
        'gameWindow': {'monsters': [{
            'coordinate': [32393, 32234, 7],
            'windowCoordinate': (400, 337),
        }]},
    }

    assert task.onTimeout(context) is context
    attack.assert_called_once_with((400, 337))


def test_walk_timeout_does_not_attack_creature_on_other_tile(mocker):
    mocker.patch(
        'src.gameplay.core.tasks.walk.releaseKeys',
        side_effect=lambda context: context,
    )
    attack = mocker.patch('src.gameplay.core.tasks.walk.mouse.attackClick')
    task = WalkTask.__new__(WalkTask)
    task.parentTask = mocker.Mock()
    task.walkpoint = [32393, 32234, 7]
    context = {
        'ng_radar': {'coordinate': [32394, 32234, 7]},
        'gameWindow': {'monsters': [{
            'coordinate': [32390, 32229, 7],
            'windowCoordinate': (208, 15),
        }]},
    }

    assert task.onTimeout(context) is context
    attack.assert_not_called()
