#!/usr/bin/python3
"""
List platforms installed by the debputy manifest.
Also check that they have distinct configurations
and that each symlink has the same configuration than its target.

flake8  debian/rules.py
pylint  debian/rules.py
mypy    debian/rules.py
python3 debian/rules.py x  # command line arguments trigger DEBUG
rm -fr .mypy_cache/
"""
import re
import sys
import yaml
DEBUG = 1 < len(sys.argv)
defconfig_to_platform: dict[str, str] = {}


class Error(Exception):
    """Used to report an issue with defconfigs."""


def defconfig(platform: str) -> str:
    """Return the contents of the defconfig file for platform."""
    with open(f'configs/{platform}_defconfig', encoding='utf-8') as stream:
        return stream.read()


def install(platform: str) -> None:
    """Check that the defconfig is unique, then print platform."""
    config = defconfig(platform)
    same = defconfig_to_platform.get(config, None)
    if same is not None:
        raise Error(f'{platform} and {same} have the same defconfig')
    defconfig_to_platform[config] = platform
    print(platform)


def symlink(alias: str, binary: str) -> None:
    """Check that alias and binary have the same defconfig."""
    config = defconfig(alias)
    same = defconfig_to_platform.get(config, None)
    if same != binary:
        raise Error(f'{alias} and {binary} have distinct defconfigs')
    if DEBUG:
        print(f'{alias:30} -> {binary}')


def main() -> None:
    """Parse the debputy manifest."""
    with open('debian/debputy.manifest', encoding='utf-8') as stream:
        manifest = yaml.safe_load(stream)
    name = '([a-z](?:[_-]?[a-z0-9]+)*)'
    fwdir = 'usr/lib/crust-firmware'
    for i in manifest['installations']:
        match i:
            case {'install': {'sources': sources, 'dest-dir': dest_dir}}:
                if dest_dir == fwdir:
                    for s in sources:
                        if (p := re.fullmatch(fr'build/{name}/\1[.]bin', s)):
                            install(platform=p.group(1))
    for t in manifest['packages']['crust-firmware']['transformations']:
        match t:
            case {'create-symlink': {'path': p, 'target': t}}:
                if (a := re.fullmatch(f'{fwdir}/{name}[.]bin', p)):
                    if (b := re.fullmatch(f'/{fwdir}/{name}[.]bin', t)):
                        symlink(alias=a.group(1), binary=b.group(1))


main()
