import pytest

from player.audio import AUDIO_SOURCES, VISUAL_POSITIONS
from player.controls import (
    Controls,
    ControlsError,
    validate_controls,
    parse_controls,
)


def test_visual_and_audio_enums_are_the_v1_positions():
    assert VISUAL_POSITIONS == frozenset({"on", "off"})
    assert AUDIO_SOURCES == frozenset({"off", "soundtrack"})


def test_valid_controls_pass_validation():
    c = Controls(visual="on", audio="soundtrack", left=0, right=4, dark=2, light=2,
                 volume=3, brightness=4)
    validate_controls(c)  # does not raise


def test_invalid_visual_position_rejected():
    c = Controls(visual="flicker", audio="off", left=0, right=0, dark=0, light=0,
                 volume=0, brightness=0)
    with pytest.raises(ControlsError):
        validate_controls(c)


def test_invalid_audio_source_rejected():
    # "music" is a reserved/deferred dial position, not a v1 source
    c = Controls(visual="on", audio="music", left=0, right=0, dark=0, light=0,
                 volume=0, brightness=0)
    with pytest.raises(ControlsError):
        validate_controls(c)


@pytest.mark.parametrize("field", ["left", "right", "dark", "light", "volume", "brightness"])
@pytest.mark.parametrize("bad", [-1, 5, True])
def test_out_of_range_or_non_int_knob_rejected(field, bad):
    kwargs = dict(visual="off", audio="off", left=0, right=0, dark=0, light=0,
                  volume=0, brightness=0)
    kwargs[field] = bad
    with pytest.raises(ControlsError):
        validate_controls(Controls(**kwargs))


def test_parse_controls_from_mapping():
    c = parse_controls(
        {"visual": "on", "audio": "soundtrack", "left": 1, "right": 2, "dark": 3,
         "light": 0, "volume": 2, "brightness": 1}
    )
    assert c == Controls("on", "soundtrack", 1, 2, 3, 0, 2, 1)


def test_parse_controls_rejects_unknown_keys():
    with pytest.raises(ControlsError):
        parse_controls({"visual": "off", "audio": "off", "left": 0, "right": 0, "dark": 0,
                        "light": 0, "volume": 0, "brightness": 0, "bogus": 1})


def test_parse_controls_rejects_missing_keys():
    with pytest.raises(ControlsError):
        parse_controls({"visual": "off", "left": 0})
