import numpy as np
import pytest


from sdia_python.lab2.ball_window import BallWindow


def test_raise_type_error_when_something_is_called():
    with pytest.raises(TypeError):
        # call_something_that_raises_TypeError()
        raise TypeError()


# ================================
# ==== WRITE YOUR TESTS BELOW ====
# ================================


@pytest.mark.parametrize(
    "center, radius, expected",
    [
        (np.array([0.0, 4.0, 5.0]), 1, "BallWindow (center : [0. 4. 5.], radius : 1)"),
        (
            np.array([1.0, 1.0, 10.0]),
            0.7,
            "BallWindow (center : [ 1.  1. 10.], radius : 0.7)",
        ),
        (
            np.array([0.0, 5.0, -1.0, 3.0]),
            np.sqrt(2),
            "BallWindow (center : [ 0.  5. -1.  3.], radius : 1.4142135623730951)",
        ),
    ],
)
def test_ball_string_representation(center, radius, expected):
    assert str(BallWindow(center, radius)) == expected


@pytest.mark.parametrize(
    "args,  expected",
    [
        # (Center coordinates, radius, point of interest), expected
        ((np.array([[2.5, 2.5]]), 10, np.array([[2.5, 2.5]])), True),
        ((np.array([[2, 5]]), 4, np.array([[2.5, 2.5]])), True),
        ((np.array([[2, 2]]), 0.5, np.array([[2.5, 2.5]])), False),
        ((np.array([[0, 2, 3]]), 0.5, np.array([[1, 2.5, 2.5]])), False),
        ((np.array([[0, 2, 3, 4]]), 5, np.array([[1, 3, 2.5, 2.5]])), True),
    ],
)
def test_in_ball_window(args, expected):
    assert BallWindow(*args[:2]).__contains__(args[-1]) == expected


@pytest.fixture
def example_ball_window():
    center = [0, 0]
    radius = 1.0
    return BallWindow(center, radius)


@pytest.mark.parametrize(
    "points, expected",
    [
        (np.array([[0, 0]]), [True]),
        (np.array([[0, 5]]), [False]),
        (np.array([[0, 0]]), [True]),
    ],
)
def test_indicator(example_ball_window, points, expected):
    ball = BallWindow(np.array([0, 0]), 1.0)
    assert ball.indicator(points) == expected


@pytest.mark.parametrize(
    "ball, expected",
    [
        (BallWindow([0, 1], 1), np.pi),
        (BallWindow([1, 0, 2], 3), 113.09733552923254),
        (BallWindow([0, -4, 1, 3], 3), 399.718978244119),
    ],
)
def test_volume(ball, expected):
    assert (ball.volume()) == expected
