import pytest

from plover.machine.keymap import Keymap


def new_keymap():
    return Keymap(("k%u" % n for n in range(8)), ("a%u" % n for n in range(4)))


BINDINGS_LIST = (
    ("k0", "a0"),
    ("k1", "a3"),
    ("k4", "a1"),
    ("k5", "a2"),
    ("k7", "a1"),
)
BINDINGS_DICT = dict(BINDINGS_LIST)
MAPPINGS_LIST = (
    ("a0", ("k0",)),
    ("a1", ("k4", "k7")),
    ("a2", ("k5",)),
    ("a3", ("k1",)),
)
MAPPINGS_DICT = dict(MAPPINGS_LIST)
MAPPINGS_FULL = dict(MAPPINGS_DICT)
MAPPINGS_FULL.update({"no-op": ()})


def test_keymap_init():
    k = new_keymap()
    assert k.get_bindings() == {}
    assert k.get_mappings() == {}


def test_keymap_set_bindings():
    # Set bindings from a dictionary.
    k = new_keymap()
    k.set_bindings(BINDINGS_DICT)
    assert k.get_bindings() == BINDINGS_DICT
    assert k.get_mappings() == MAPPINGS_FULL
    # Set bindings from a list of tuples.
    k = new_keymap()
    k.set_bindings(BINDINGS_LIST)
    assert k.get_bindings() == BINDINGS_DICT
    assert k.get_mappings() == MAPPINGS_FULL


def test_keymap_set_mappings():
    # Set mappings from a dictionary.
    k = new_keymap()
    k.set_mappings(MAPPINGS_DICT)
    assert k.get_bindings() == BINDINGS_DICT
    assert k.get_mappings() == MAPPINGS_FULL
    # Set mappings from a list of tuples.
    k = new_keymap()
    k.set_mappings(MAPPINGS_LIST)
    assert k.get_bindings() == BINDINGS_DICT
    assert k.get_mappings() == MAPPINGS_FULL


def test_keymap_setitem():
    bindings = dict(BINDINGS_DICT)
    mappings = dict(MAPPINGS_FULL)
    k = new_keymap()
    k.set_mappings(mappings)
    # Bind to one key.
    k["a3"] = "k6"
    del bindings["k1"]
    bindings["k6"] = "a3"
    mappings["a3"] = ("k6",)
    assert k.get_bindings() == bindings
    assert k.get_mappings() == mappings
    # Bind to multiple keys.
    k["a3"] = ("k6", "k1")
    bindings["k1"] = "a3"
    bindings["k6"] = "a3"
    mappings["a3"] = (
        "k1",
        "k6",
    )
    assert k.get_bindings() == bindings
    assert k.get_mappings() == mappings
    # If a key is already mapped (k0), don't override it.
    k["a3"] = ("k0", "k2")
    del bindings["k1"]
    del bindings["k6"]
    bindings["k2"] = "a3"
    mappings["a3"] = ("k2",)
    assert k.get_bindings() == bindings
    assert k.get_mappings() == mappings
    # Assert on invalid action.
    with pytest.raises(AssertionError):
        k["a9"] = "k0"
