import pytest
from enum import Enum

from pybusmonitor1553.lib1553.message_base import MessageBase
from pybusmonitor1553.lib1553.fields import BitField, EnumField, ScaledField, ASCIIField


class DummyMsg(MessageBase):
    pass


def test_bitfield_get_set():
    class M(DummyMsg):
        bf = BitField(word_index=0, start_bit=0, width=3)

    m = M()
    # initial 0
    assert m.bf == 0
    m.bf = 5
    assert m.bf == 5
    # underlying word contains shifted value
    assert m.data[0] != 0


def test_enumfield_with_enum_and_raw():
    class E(Enum):
        A = 0
        B = 1

    class M(DummyMsg):
        ef = EnumField(word_index=1, start_bit=0, enum_cls=E, width=1)

    m = M()
    # set with enum
    m.ef = E.B
    assert m.ef == E.B
    # set with raw int
    m.ef = 0
    assert m.ef == E.A


def test_scaledfield_signed_unsigned():
    class M(DummyMsg):
        s1 = ScaledField(word_index=2, start_bit=0, width=16, lsb_value=0.5, signed=False)
        s2 = ScaledField(word_index=3, start_bit=0, width=8, lsb_value=1.0, signed=True)

    m = M()
    m.s1 = 10.0
    assert pytest.approx(m.s1, rel=1e-6) == 10.0

    # signed field: set negative
    m.s2 = -3.0
    assert pytest.approx(m.s2, rel=1e-6) == -3.0


def test_asciifield_get_set_and_validation():
    class M(DummyMsg):
        a = ASCIIField(word_index=4)

    m = M()
    m.a = 'OK'
    assert m.a == 'OK'

    with pytest.raises(ValueError):
        m.a = 'TOO_LONG'
