#!/usr/bin/env python3
# Copyright 2019 Collabora Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# (See debian/copyright)

import os
import shutil
import subprocess

try:
    from typing import (
        Dict,
        IO,
        Set,
    )
    # placate pyflakes
    Dict, IO, Set
except ImportError:
    pass

import steamrt_abi


def gensymbols(
    lib,            # type: steamrt_abi.Library
    architecture,   # type: steamrt_abi.Architecture
    package,        # type: str
    writer,         # type: IO[str]
) -> bool:
    if not lib.track_abi:
        return False

    for prefix in ('/usr', '/'):
        libpath = os.path.join(
            prefix,
            'lib',
            architecture.multiarch_tuple,
            lib.soname,
        )

        if os.path.exists(libpath):
            break
    else:
        return False

    version = '0'   # stub, we don't use this for anything yet

    argv = [
        'dpkg-gensymbols',
        '-p' + package,
        '-e' + libpath,
        '-v' + version,
        '-I/dev/null',
        '-q',
        '-O-',
    ]

    with subprocess.Popen(
        argv, stdout=subprocess.PIPE, universal_newlines=True,
    ) as dgs:
        stdout = dgs.stdout
        assert stdout is not None

        for line in stdout:
            if line.startswith(' '):
                assert not line[1:].startswith(' '), line
                assert ' ' in line[1:], line
                symbol, version = line[1:].split(None, 1)
                assert symbol, line
                assert version, line
                assert '@' in symbol, line
                symbol, symver = symbol.split('@', 1)

                if symbol == symver:
                    public = (
                        lib.public_symbol_versions
                        and lib.symbol_version_is_public(symver)
                    )
                else:
                    public = (
                        lib.public_symbols
                        and lib.symbol_is_public(symbol, symver)
                    )

                if public:
                    writer.write(line)
            else:
                writer.write(line)

    return True


def main() -> None:
    abi = steamrt_abi.AbiData()

    for multiarch_tuple in abi.architectures:
        # { 'zlib1g': set(['libz.so.1']) }
        packages = {}   # type: Dict[str, Set[str]]

        output_dir = os.path.join(
            os.path.dirname(__file__),
            'expectations',
            multiarch_tuple,
        )

        try:
            shutil.rmtree(output_dir)
        except OSError:
            pass

        os.makedirs(output_dir)

        for lib in abi.shared_libraries.values():
            packages.setdefault(lib.deb, set()).add(lib.soname)

        for package, sonames in packages.items():
            for soname in sonames:
                lib = abi.shared_libraries[soname]

                if lib.check_loadable:
                    break
            else:   # didn't break
                continue

            with open(
                os.path.join(output_dir, package + '.symbols'),
                'w'
            ) as writer:
                for soname in sorted(sonames):
                    lib = abi.shared_libraries[soname]

                    if not lib.check_loadable:
                        continue

                    if not gensymbols(
                        lib,
                        abi.architectures[multiarch_tuple],
                        package,
                        writer,
                    ):
                        writer.write('{} {} #MINVER#\n'.format(
                            soname,
                            package,
                        ))
                        writer.write('# No symbols listed here yet\n')


if __name__ == '__main__':
    main()
