from bombahead import Action, Bomb, CellType, Field, GameHelpers, GameState, Position


def test_is_walkable() -> None:
    state = GameState(
        field=Field(
            width=3,
            height=3,
            cells=[
                CellType.AIR,
                CellType.WALL,
                CellType.AIR,
                CellType.AIR,
                CellType.BOX,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
            ],
        ),
        bombs=[Bomb(pos=Position(2, 2), fuse=3)],
    )
    helpers = GameHelpers(state)

    assert not helpers.is_walkable(Position(-1, 0))
    assert not helpers.is_walkable(Position(1, 0))
    assert not helpers.is_walkable(Position(1, 1))
    assert not helpers.is_walkable(Position(2, 2))
    assert helpers.is_walkable(Position(0, 0))


def test_get_adjacent_walkable_positions() -> None:
    state = GameState(
        field=Field(
            width=3,
            height=3,
            cells=[
                CellType.AIR,
                CellType.WALL,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
            ],
        ),
        bombs=[Bomb(pos=Position(2, 1), fuse=3)],
    )
    helpers = GameHelpers(state)

    got = helpers.get_adjacent_walkable_positions(Position(1, 1))
    assert got == [Position(1, 2), Position(0, 1)]


def test_get_next_action_towards() -> None:
    state = GameState(
        field=Field(
            width=5,
            height=5,
            cells=[CellType.AIR] * 25,
        )
    )
    helpers = GameHelpers(state)

    assert helpers.get_next_action_towards(Position(1, 1), Position(3, 1)) == Action.MOVE_RIGHT
    assert helpers.get_next_action_towards(Position(2, 2), Position(2, 2)) == Action.DO_NOTHING

    state.field = Field(
        width=3,
        height=3,
        cells=[
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.WALL,
            CellType.WALL,
            CellType.AIR,
            CellType.WALL,
            CellType.AIR,
        ],
    )
    assert helpers.get_next_action_towards(Position(0, 0), Position(2, 2)) == Action.DO_NOTHING


def test_is_safe_with_blast_blocking_and_chain_reaction() -> None:
    state = GameState(
        field=Field(
            width=5,
            height=5,
            cells=[
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.WALL,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
            ],
        ),
        bombs=[Bomb(pos=Position(2, 2), fuse=1), Bomb(pos=Position(4, 2), fuse=5)],
        explosions=[Position(0, 0)],
    )
    helpers = GameHelpers(state)

    assert not helpers.is_safe(Position(2, 3))
    assert not helpers.is_safe(Position(4, 4))
    assert not helpers.is_safe(Position(0, 0))
    assert helpers.is_safe(Position(2, 0))


def test_get_nearest_safe_position() -> None:
    state = GameState(
        field=Field(width=5, height=5, cells=[CellType.AIR] * 25),
        bombs=[Bomb(pos=Position(2, 2), fuse=1)],
    )
    helpers = GameHelpers(state)

    assert helpers.get_nearest_safe_position(Position(0, 0)) == Position(0, 0)
    assert helpers.get_nearest_safe_position(Position(2, 2)) == Position(3, 1)


def test_find_nearest_box() -> None:
    state = GameState(
        field=Field(
            width=4,
            height=3,
            cells=[
                CellType.AIR,
                CellType.BOX,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.WALL,
                CellType.WALL,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
                CellType.AIR,
            ],
        )
    )
    helpers = GameHelpers(state)

    assert helpers.find_nearest_box(Position(0, 0)) == (Position(1, 0), True)

    state.field = Field(
        width=4,
        height=3,
        cells=[
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.WALL,
            CellType.WALL,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
            CellType.AIR,
        ],
    )
    _, ok = helpers.find_nearest_box(Position(0, 0))
    assert not ok
