#!/usr/bin/python3 -B


from argparse import ArgumentParser, Namespace
import sys
from textwrap import dedent

from config import Signing


def gen_depends_uci(signing: Signing):
    uci_archs = signing.option_archs("uci")
    if uci_archs:
        print(
            f' ubuntu-core-initramfs [{" ".join(sorted(uci_archs))}] <pkg.linux-generate>,'
        )
        print(f' cpio <pkg.linux-generate>,')

def gen_depends_stubble(signing: Signing):
    stubble_archs = signing.option_archs("stubble")
    if stubble_archs:
        print(f' stubble-kernel [{" ".join(sorted(stubble_archs))}] <pkg.linux-generate>,')

def gen_depends_efi(signing: Signing):
    efi_archs = set()
    for (arch, flavour), (stype, binary) in signing.arch_flavour_data:
        if stype == "efi":
            efi_archs.update([arch])
    if efi_archs:
        print(f' sbsigntool [{" ".join(sorted(efi_archs))}],')


def gen_depends(signing: Signing, args: Namespace):
    for flavour, archs in signing.flavour_archs:
        print(
            f' linux-image-unsigned-{args.abi_version}-{flavour} (= {args.unsigned_version}) [{" ".join(archs)}],'
        )
        stubble_archs = signing.flavour_option_archs(flavour, "stubble") & set(archs)
        if len(stubble_archs):
            print(
                f' linux-modules-{args.abi_version}-{flavour} (= {args.unsigned_version}) [{" ".join(stubble_archs)}] <pkg.linux-generate>,'
            )
        print(
            f' linux-buildinfo-{args.abi_version}-{flavour} (= {args.unsigned_version}) [{" ".join(archs)}],'
        )
    # generate-only build-depends with a profile
    # (activated by debian/scripts/parameterise-ancillaries)
    gen_depends_uci(signing)
    gen_depends_stubble(signing)
    print(f" {args.generate_name} (= {args.source_version}) <!pkg.linux-generate>,")
    for flavour, archs in signing.package_flavour_archs("extra"):
        # ubuntu-core-initramfs sometime needs extra modules https://bugs.launchpad.net/bugs/2032760
        print(
            f' linux-modules-extra-{args.abi_version}-{flavour} (= {args.unsigned_version}) [{" ".join(sorted(archs))}]  <pkg.linux-generate>,'
        )
    gen_depends_efi(signing)
    # For HMACs
    print(f" openssl,")


def replace_placeholders(signing: Signing, args: Namespace):
    for line in sys.stdin.readlines():
        line = line.replace("@SRCPKGNAME@", args.source_name)
        line = line.replace("@SERIES@", args.series)
        if "@DEPENDS@" in line:
            gen_depends(signing, args)
        else:
            print(line, end="")


def gen_binpkgs(signing: Signing, args: Namespace):
    for flavour, archs in signing.package_flavour_archs("image"):
        print(
            dedent(
                f"""\

            Package: linux-image-{args.abi_version}-{flavour}
            Architecture: {" ".join(archs)}
            Depends: ${{unsigned:Depends}}
            Recommends: ${{unsigned:Recommends}}
            Suggests: ${{unsigned:Suggests}}
            Conflicts: ${{unsigned:Conflicts}}
            Provides: ${{unsigned:Provides}}
            Built-Using: {args.unsigned_name} (= {args.unsigned_version})
            Description: Signed kernel image {flavour}
             A kernel image for {flavour}.  This version of it is signed with
             Canonical's signing key.
            """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("di"):
        print(
            dedent(
                f"""\

            Package: kernel-signed-image-{args.abi_version}-{flavour}-di
            Package-Type: udeb
            Section: debian-installer
            Priority: extra
            Provides: kernel-signed-image
            Architecture: {" ".join(archs)}
            Built-Using: {args.unsigned_name} (= {args.unsigned_version})
            Description: Signed kernel image {flavour} for the Debian installer
             A kernel image for {flavour}.  This version of it is signed with
             Canonical's UEFI signing key.  It is intended for the Debian installer,
             it does _not_ provide a usable kernel for your full Debian system.
        """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("hmac"):
        print(
            dedent(
                f"""\

            Package: linux-image-hmac-{args.abi_version}-{flavour}
            Build-Profiles: <!stage1>
            Architecture: {" ".join(archs)}
            Section: kernel
            Priority: optional
            Depends: ${{misc:Depends}}, ${{shlibs:Depends}}, linux-image-{args.abi_version}-{flavour}
            Suggests: fips-initramfs-generic
            Description: HMAC file for linux kernel image {args.abi_version}-{flavour}
             This package contains the HMAC file for Linux kernel image for version
             {args.abi_version}-{flavour}
            """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("cvm"):
        # Mostly similar to image, but we don't have recommands nor conflicts
        print(
            dedent(
                f"""\

            Package: linux-image-{args.abi_version}-{flavour}-fde
            Architecture: {" ".join(archs)}
            Depends: ${{unsigned:Depends}}
            Recommends: ${{cvm:Recommends}}
            Suggests: ${{unsigned:Suggests}}
            Conflicts: ${{cvm:Conflicts}}
            Provides: ${{unsigned:Provides}}
            Built-Using: {args.unsigned_name} (= {args.unsigned_version})
            Description: Signed kernel image {flavour} for CVM
             A kernel image for {flavour}.  This version of it is signed with
             Canonical's signing key.
            """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("uc"):
        depends = f"linux-modules-{args.abi_version}-{flavour}"
        for extra_flavour, extra_archs in signing.package_flavour_archs("extra"):
            if extra_flavour == flavour:
                depends += f", linux-modules-extra-{args.abi_version}-{flavour} [{' '.join(sorted(extra_archs))}]"
        # Mostly similar to image, but we don't have recommands nor conflicts
        print(
            dedent(
                f"""\

            Package: linux-image-uc-{args.abi_version}-{flavour}
            Architecture: {" ".join(archs)}
            Depends: {depends}
            Built-Using: {args.unsigned_name} (= {args.unsigned_version})
            Description: Signed kernel image {flavour} for Ubuntu Core
             A kernel image for {flavour}.  This version of it is signed with
             Canonical's signing key.
            """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("fallback"):
        depends = f"linux-modules-{args.abi_version}-{flavour}"
        for extra_flavour, extra_archs in signing.package_flavour_archs("extra"):
            if extra_flavour == flavour:
                depends += f", linux-modules-extra-{args.abi_version}-{flavour} [{' '.join(sorted(extra_archs))}]"
        # Mostly similar to image, but we don't have recommands nor conflicts
        print(
            dedent(
                f"""\

            Package: linux-image-fb-{args.abi_version}-{flavour}
            Architecture: {" ".join(archs)}
            Depends: ${{unsigned:Depends}}
            Recommends: ${{unsigned:Recommends}}
            Suggests: ${{unsigned:Suggests}}
            Conflicts: ${{unsigned:Conflicts}}
            Provides: ${{unsigned:Provides}}
            Built-Using: {args.unsigned_name} (= {args.unsigned_version})
            Description: Signed kernel image {flavour} (Stubble)
             A kernel image for {flavour}.  This version of it is signed with
             Canonical's signing key.  Delivered as a stubble payload.
             Fallback kernel without stubble wrapper.
            """
            ).rstrip()
        )


def gen_dbgsym_binpkgs(signing: Signing, args: Namespace):
    for flavour, archs in signing.package_flavour_archs("image"):
        print(
            dedent(
                f"""\

            Package: linux-image-{args.abi_version}-{flavour}-dbgsym
            Section: devel
            Architecture: {" ".join(archs)}
            Depends: linux-image-unsigned-{args.abi_version}-{flavour}-dbgsym
            Description: Signed kernel image {flavour}
             A link to the debugging symbols for the {flavour} signed kernel.
            """
            ).rstrip()
        )
    for flavour, archs in signing.package_flavour_archs("cvm"):
        print(
            dedent(
                f"""\

            Package: linux-image-{args.abi_version}-{flavour}-fde-dbgsym
            Section: devel
            Architecture: {" ".join(archs)}
            Depends: linux-image-unsigned-{args.abi_version}-{flavour}-dbgsym
            Description: Signed kernel image {flavour} for CVM (debug)
             A link to the debugging symbols for the {flavour} signed kernel.
            """
            ).rstrip()
        )


def main(signing: Signing, args: Namespace):

    replace_placeholders(signing, args)
    gen_binpkgs(signing, args)

    # XXX: all dbgsym packages _must_ be at the end of debian/control else the
    # build will hang forever on the builder.
    gen_dbgsym_binpkgs(signing, args)


if __name__ == "__main__":

    parser = ArgumentParser(
        prog="generate_control.py",
        description="generate debian/control file from debian/control.stub",
        epilog="pass debian/control.stub as stdin and get debian/control as stdout",
    )

    parser.add_argument("series")
    parser.add_argument("source_name")
    parser.add_argument("generate_name")
    parser.add_argument("source_version")
    parser.add_argument("unsigned_name")
    parser.add_argument("unsigned_version")
    parser.add_argument("abi_version")

    args = parser.parse_args()
    signing = Signing.load("debian/package.config")

    main(signing, args)
