#!/usr/bin/env python3
#
# Call with pytest. Requires XKB_CONFIG_ROOT to be set

import os
import subprocess
import sys
from pathlib import Path

import pytest


def _xkb_config_root() -> list[Path]:
    roots: list[Path] = []

    # XKB_CONFIG_EXTRA_PATH is not mandatory
    if path := os.getenv("XKB_CONFIG_EXTRA_PATH"):
        roots.append(Path(path))
        print(f"Using XKB_CONFIG_EXTRA_PATH={path}")

    if path := os.getenv("XKB_CONFIG_ROOT"):
        xkbpath = Path(path)
        assert (xkbpath / "symbols").exists(), f"{path} is not an XKB installation"
        roots.append(xkbpath)
        print(f"Using XKB_CONFIG_ROOT={path}")
    else:
        raise ValueError("Environment variable XKB_CONFIG_ROOT must be set")

    return roots


@pytest.fixture
def xkb_config_root():
    return _xkb_config_root()


def pytest_generate_tests(metafunc):
    # for any test_foo function with an argument named xkb_symbols,
    # make it a list of tuples in the form (us, dvorak)
    # The list is generated by scanning all xkb symbol files and extracting the
    # various sections
    if "xkb_symbols" in metafunc.fixturenames:
        xkb_symbols = []
        # This skips the *_vndr directories, they're harder to test
        for root in _xkb_config_root():
            for symbols_file in root.glob("symbols/*"):
                if symbols_file.is_dir():
                    continue
                with open(symbols_file) as f:
                    print(f"Found file {symbols_file}")
                    for line in f:
                        if not line.startswith('xkb_symbols "'):
                            continue
                        section = line.split('"')[1]
                        entry = (symbols_file.name, section)
                        if entry not in xkb_symbols:
                            xkb_symbols.append(entry)
        assert xkb_symbols
        metafunc.parametrize("xkb_symbols", xkb_symbols)


def test_xkbcomp(xkb_config_root, xkb_symbols):
    layout, variant = xkb_symbols
    keymap = f"""
xkb_keymap {{
        xkb_keycodes  {{ include "evdev+aliases(qwerty)" }};
        xkb_types     {{ include "complete"      }};
        xkb_compat    {{ include "complete"      }};
        xkb_symbols   {{ include "pc+{layout}({variant})"     }};
}};
"""
    print(keymap)

    args = [
        "xkbcomp",
        "-w0",  # reduce warning nose
        "-xkb",
        "-I",  # disable system includes
    ]
    args += [f"-I{p}" for p in xkb_config_root]
    args += [
        "-",  # from stdin
        "-",  # to stdout
    ]
    p = subprocess.run(args, input=keymap, encoding="utf-8", capture_output=True)
    if p.stderr:
        print(p.stderr, file=sys.stderr)
    if p.returncode != 0:
        print(p.stdout)
    if p.returncode < 0:
        print(f"xkbcomp exited with signal {-p.returncode}", file=sys.stderr)

    assert p.returncode == 0
