import pytest

from .. bfclass import BitFlag


FL_ONE = 'FL_ONE'
FL_TWO = 'FL_TWO'
FL_THREE = 'FL_THREE'
FL_FOUR = 'FL_FOUR'

FLAGS = [
    'FL_ONE',
    'FL_TWO',
    'FL_THREE',
    'FL_FOUR'
]


def test_internals():
    bf = BitFlag(FLAGS)
    assert bf._get_bit(FL_TWO) == 2
    assert bf._get_bit(FL_THREE) == 4

def test_init_error():
    with pytest.raises(TypeError):
        bf = BitFlag({})
    with pytest.raises(ValueError):
        bf = BitFlag([])
    with pytest.raises(ValueError):
        bf = BitFlag(['_arggh','_meong_','other__'])
    with pytest.raises(ValueError):
        bf = BitFlag(['as_int','as_dict'])

def test_init_more_than_64_flags():
    with pytest.raises(OverflowError):
        BitFlag(list(map(lambda x: 'flag' + str(x), range(66))))

def test_flag_special_characters():
    bf = BitFlag([';arggh','(meong','**other'])
    bf[';arggh'] = True
    assert bf[';arggh'] == True
    assert bf.as_int() == 1

def test_setting_flag():
    bf = BitFlag(FLAGS)
    bf.FL_ONE = True
    assert bf.as_int() == 1
    assert bf.FL_ONE == True
    bf.FL_THREE = True
    assert bf.as_int() == 5
    assert bf.FL_THREE == True
    bf.FL_ONE = False
    assert bf.as_int() == 4
    assert bf.FL_ONE == False
    with pytest.raises(KeyError):
        bf.FL_SIX = True
    with pytest.raises(ValueError):
        bf.FL_ONE = 'meong'

def test_setting_flag_dict_style():
    bf = BitFlag(FLAGS)
    bf[FL_ONE] = True
    assert bf.as_int() == 1
    assert bf[FL_ONE] == True
    bf[FL_THREE] = True
    assert bf.as_int() == 5
    assert bf[FL_THREE] == True
    bf[FL_ONE] = False
    assert bf.as_int() == 4
    assert bf[FL_ONE] == False
    with pytest.raises(KeyError):
        bf['FL_SIX'] = True
    with pytest.raises(ValueError):
        bf[FL_ONE] = 'meong'

def test_init_with_existing_flags():
    bf = BitFlag(FLAGS, 5)
    assert bf.FL_ONE == True
    assert bf.FL_TWO == False
    assert bf.FL_THREE == True
    assert bf.as_int() == 5

def test_as_dict():
    dflag = {
        'FL_ONE': True,
        'FL_TWO': False,
        'FL_THREE': True,
        'FL_FOUR': False,
    }
    bf = BitFlag(FLAGS, 5)
    assert bf.as_dict() == dflag

def test_as_list():
    dflag = [
        ('FL_ONE', True),
        ('FL_TWO', False),
        ('FL_THREE', True),
        ('FL_FOUR', False),
    ]
    bf = BitFlag(FLAGS, 5)
    assert bf.as_list() == dflag

def test_compare():
    bf = BitFlag(FLAGS, 1)
    dflag = {
        'FL_ONE': False,
        'FL_THREE': True,
    }
    assert bf.compare(4) == dflag
    assert bf.as_int() == 1

def test_update():
    bf = BitFlag(FLAGS, 1)
    dflag = {
        'FL_ONE': False,
        'FL_THREE': True,
    }
    assert bf.update(4) == dflag
    assert bf.as_int() == 4