import importlib.util
from pathlib import Path
from unittest.mock import Mock

import pytest


def load_lock_command(command_file):
    command_path = (
        Path(__file__).resolve().parents[2]
        / "src"
        / "fenrirscreenreader"
        / "commands"
        / "onKeyInput"
        / command_file
    )
    spec = importlib.util.spec_from_file_location(
        command_file.replace("-", "_"), command_path
    )
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module.command


def build_env(input_data):
    output_manager = Mock()
    return {
        "input": input_data,
        "runtime": {
            "OutputManager": output_manager,
        },
    }, output_manager


@pytest.mark.unit
def test_capslock_command_ignores_non_capslock_state_change():
    command = load_lock_command("80000-capslock.py")()
    env, output_manager = build_env(
        {
            "old_caps_lock": False,
            "new_caps_lock": True,
            "curr_input": ["KEY_KP8"],
            "prev_input": [],
        }
    )
    command.initialize(env)

    command.run()

    output_manager.present_text.assert_not_called()


@pytest.mark.unit
def test_capslock_command_announces_capslock_release_change():
    command = load_lock_command("80000-capslock.py")()
    env, output_manager = build_env(
        {
            "old_caps_lock": True,
            "new_caps_lock": False,
            "curr_input": [],
            "prev_input": ["KEY_CAPSLOCK"],
        }
    )
    command.initialize(env)

    command.run()

    output_manager.present_text.assert_called_once()
    assert output_manager.present_text.call_args.args[0] == "Capslock off"


@pytest.mark.unit
def test_scrolllock_command_ignores_non_scrolllock_state_change():
    command = load_lock_command("80300-scrolllock.py")()
    env, output_manager = build_env(
        {
            "old_scroll_lock": False,
            "new_scroll_lock": True,
            "curr_input": ["KEY_KP8"],
            "prev_input": [],
        }
    )
    command.initialize(env)

    command.run()

    output_manager.present_text.assert_not_called()


@pytest.mark.unit
def test_scrolllock_command_announces_scrolllock_release_change():
    command = load_lock_command("80300-scrolllock.py")()
    env, output_manager = build_env(
        {
            "old_scroll_lock": True,
            "new_scroll_lock": False,
            "curr_input": [],
            "prev_input": ["KEY_SCROLLLOCK"],
        }
    )
    command.initialize(env)

    command.run()

    output_manager.present_text.assert_called_once()
    assert output_manager.present_text.call_args.args[0] == "Scrolllock off"
