"""
SPDX-License-Identifier: LGPL-2.1-or-later
SPDX-FileCopyrightText: 2020 CERN
"""

from pathlib import Path
import pytest
from PyFmcFineDelay import FmcFineDelay
import re


def valid_slot_type(slot):
    if re.search(r"(VME|PCI)\.[0-9]+-FMC\.[0-9]+", slot) is None:
        raise ValueError()
    return slot


def id_from_slot(slot):
    carrier, mezzanine = slot.split("-")
    carrier_bus, carrier_slot = carrier.split(".")
    carrier_slot = int(carrier_slot)
    mezzanine_bus, mezzanine_slot = mezzanine.split(".")
    mezzanine_slot = int(mezzanine_slot)
    if carrier_bus == "PCI":
        with open("/run/dynpci") as f:
            for line in f.readlines():
                dynslot, pciid = line.strip().split(" ")
                if int(dynslot) == carrier_slot:
                    break
        pciid = f"0000:{pciid}"
        pathfmc = list(Path("/sys/bus/pci/devices").joinpath(pciid)
                                                   .glob(f"spec-*/id:*/fmc-fdelay-tdc.*.auto/fmc-slot-*.{mezzanine_slot}"))
    elif carrier_bus == "VME":

        pathfmc = list(Path("/sys/bus/vme/devices").joinpath(f"slot.{carrier_slot:02d}")
                                                   .joinpath(f"vme.{carrier_slot:02d}")
                                                   .glob(f"svec-*/svec-*/id:*/fmc-fdelay-tdc.*.auto/fmc-slot-*.{mezzanine_slot}"))
    else:
        raise ValueError()

    assert len(pathfmc) == 1
    devname = list(Path(pathfmc[0]).parent.glob("hw-fd-*/fd-*/devname"))
    assert len(devname) == 1
    with open(devname[0]) as f:
        dev_id = int(f.read().strip().split("-")[1], 16)
    return dev_id


def pytest_generate_tests(metafunc):
    if "dev_id" in metafunc.fixturenames:
        metafunc.parametrize("dev_id", pytest.dev_id)


@pytest.fixture(scope="function")
def fmcfd(dev_id):
    fd = FmcFineDelay(dev_id)
    for ch in fd.chan:
        ch.disable()
    yield fd
    for chan in fd.chan:
        chan.disable()


def pytest_addoption(parser):
    parser.addoption("--id", type=lambda x: int(x, 16), action='append',
                     default=[], help="Fmc Fine-Delay Linux Identifier")
    parser.addoption("--slot", type=valid_slot_type, action='append',
                     default=[], help="Fmc Fine-Delay absolute slot (works only for SPEC and SVEC)")
    parser.addoption("--channel", type=int, default=[],
                     action="append", choices=range(FmcFineDelay.CHANNEL_NUMBER),
                     help="Channel(s) to be used for acquisition tests. Default all channels")


def pytest_configure(config):
    pytest.dev_id = config.getoption("--id")
    if len(pytest.dev_id) == 0:
        pytest.slot = config.getoption("--slot")
        if len(pytest.slot) == 0:
            print("Missing argument --id or --slot")
            raise Exception()
        pytest.dev_id = []
        for slot in pytest.slot:
            pytest.dev_id.append(id_from_slot(slot))
    pytest.channels = config.getoption("--channel")
    if len(pytest.channels) == 0:
        pytest.channels = range(FmcFineDelay.CHANNEL_NUMBER)
