"""
Utility functions for reading and writing toml files.

Handles module imports for all supported versions (in a build root or on a host).
"""
import importlib
from types import ModuleType
from typing import Optional

# Different modules require different file mode (text vs binary)
_toml_modules = {
    "tomllib": {"mode": "rb"},  # stdlib since 3.11 (read-only)
    "tomli": {"mode": "rb"},  # EL9+
    "toml": {"mode": "r", "encoding": "utf-8"},  # older unmaintained lib, needed for backwards compatibility
    "pytoml": {"mode": "r", "encoding": "utf-8"},  # deprecated, needed for backwards compatibility (EL8 manifests)
}


_toml: Optional[ModuleType] = None
_rargs: dict = {}
for module, args in _toml_modules.items():
    try:
        _toml = importlib.import_module(module)
        _rargs = args
        break
    except ModuleNotFoundError:
        pass
else:
    raise ModuleNotFoundError("No toml module found: " + ", ".join(_toml_modules))

# Different modules require different file mode (text vs binary)
_tomlw_modules = {
    "tomli_w": {"mode": "wb"},  # EL9+
    "toml": {"mode": "w", "encoding": "utf-8"},  # older unmaintained lib, needed for backwards compatibility
    "pytoml": {"mode": "w", "encoding": "utf-8"},  # deprecated, needed for backwards compatibility (EL8 manifests)
}


_tomlw: Optional[ModuleType] = None
_wargs: dict = {}
for module, args in _tomlw_modules.items():
    try:
        _tomlw = importlib.import_module(module)
        _wargs = args
        break
    except ModuleNotFoundError:
        # allow importing without write support
        pass


def load_from_file(path):
    if _toml is None:
        raise RuntimeError("no toml module available")

    with open(path, **_rargs) as tomlfile:  # pylint: disable=unspecified-encoding
        return _toml.load(tomlfile)


def dump_to_file(data, path, header=""):
    if _tomlw is None:
        raise RuntimeError("no toml module available with write support")

    with open(path, **_wargs) as tomlfile:  # pylint: disable=unspecified-encoding
        if header:
            _write_comment(tomlfile, header)

        _tomlw.dump(data, tomlfile)


def _write_comment(f, comment: list):
    if not comment:
        return

    data = "\n".join(map(lambda c: f"# {c}", comment)) + "\n\n"
    if "b" in f.mode:
        f.write(data.encode())
    else:
        f.write(data)
