#!/usr/bin/env fuchsia-vendored-python
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import dataclasses
import os
import re
from typing import TextIO

from assembly import AssemblyInputBundle, PackageManifest
from depfile import DepFile
from serialization.serialization import json_load

_RUST_LIBSTD_RE = re.compile("lib\/libstd-[a-z0-9]+\.so")
_RUST_LIBSTD_WILDCARD = "lib/libstd-*"


@dataclasses.dataclass
class CollectedArtifacts(object):
    static_packages: set[str]
    bootfs_packages: set[str]
    bootfs_files: set[str]
    kernel_cmdline: set[str]
    deps: list[str]


def collect_aib_artifacts(
    aib: AssemblyInputBundle, aib_path: str
) -> CollectedArtifacts:
    static_packages = set()
    bootfs_packages = set()
    for pkg in aib.packages:
        package_str = str(pkg.package)
        if pkg.set == "base":
            name = package_str.removeprefix("packages/")
            static_packages.add(name)
        elif pkg.set == "cache":
            name = package_str.removeprefix("packages/")
            static_packages.add(name)
        elif pkg.set == "flexible":
            name = package_str.removeprefix("packages/")
            static_packages.add(name)
        elif pkg.set == "bootfs":
            name = package_str.removeprefix("packages/")
            bootfs_packages.add(name)
    for base_driver in aib.base_drivers:
        name = str(base_driver.package).removeprefix("packages/")
        static_packages.add(name)
    for boot_driver in aib.boot_drivers:
        name = str(boot_driver.package).removeprefix("packages/")
        bootfs_packages.add(name)

    bootfs_files = set()
    deps = []
    if aib.bootfs_files_package:
        manifest_path = os.path.join(aib_path, aib.bootfs_files_package)
        deps.append(manifest_path)
        with open(manifest_path, "r") as f:
            manifest = json_load(PackageManifest, f)
            for blob in manifest.blobs:
                blob_path = str(blob.path)
                if blob_path.startswith("meta/"):
                    continue
                path = blob_path.removeprefix("bootfs/")
                bootfs_files.add(path)

    cmdline = set()
    cmdline.update(aib.kernel.args)
    cmdline.update(aib.boot_args)

    return CollectedArtifacts(
        static_packages, bootfs_packages, bootfs_files, cmdline, deps
    )


class Golden:
    def __init__(self) -> None:
        self.lines: set[str] = set()

    def add_optional(self, names: set[str]) -> None:
        for name in names:
            name = name.strip()
            if name not in self.lines:
                self.lines.add("?" + name)

    def add_required(self, names: set[str]) -> None:
        for name in names:
            name = name.strip()
            optional = "?" + name
            if optional in self.lines:
                self.lines.remove(optional)
            if _RUST_LIBSTD_RE.match(name):
                name = _RUST_LIBSTD_WILDCARD
            self.lines.add(name)

    def write(self, output: TextIO) -> None:
        lines = sorted(self.lines, key=lambda s: s.removeprefix("?"))
        for line in lines:
            output.write(line + "\n")


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Tool that parses AIBs and generates relevant scrutiny configs for the platform"
    )
    parser.add_argument(
        "--assembly-input-bundles",
        nargs="+",
        type=argparse.FileType("r"),
        help="Path to an assembly input bundle config to search for artifacts",
    )
    parser.add_argument(
        "--required-assembly-input-bundles",
        nargs="+",
        type=argparse.FileType("r"),
        help="Path to an assembly input bundle config to search for artifacts",
    )
    parser.add_argument(
        "--static-packages-input",
        type=argparse.FileType("r"),
        help="Optional static packages to merge in",
    )
    parser.add_argument(
        "--bootfs-packages-input",
        type=argparse.FileType("r"),
        help="Optional bootfs packages to merge in",
    )
    parser.add_argument(
        "--bootfs-files-input",
        type=argparse.FileType("r"),
        help="Optional list of bootfs packages to merge in",
    )
    parser.add_argument(
        "--kernel-args-input",
        type=argparse.FileType("r"),
        help="Optional list of kernel arguments to merge in",
    )
    parser.add_argument(
        "--static-packages-output",
        required=True,
        type=argparse.FileType("w"),
        help="Path to the output list of static packages",
    )
    parser.add_argument(
        "--bootfs-packages-output",
        required=True,
        type=argparse.FileType("w"),
        help="Path to the output list of bootfs packages",
    )
    parser.add_argument(
        "--bootfs-files-output",
        required=True,
        type=argparse.FileType("w"),
        help="Path to the output list of bootfs files",
    )
    parser.add_argument(
        "--kernel-cmdline-output",
        required=True,
        type=argparse.FileType("w"),
        help="Path to the output list of kernel cmdlines",
    )
    parser.add_argument(
        "--depfile",
        type=argparse.FileType("w"),
    )

    args = parser.parse_args()

    deps = []
    static_packages = Golden()
    bootfs_packages = Golden()
    bootfs_files = Golden()
    kernel_cmdline = Golden()

    for file in args.assembly_input_bundles:
        aib_path = os.path.dirname(file.name)
        aib = json_load(AssemblyInputBundle, file)

        artifacts = collect_aib_artifacts(aib, aib_path)
        deps.extend(artifacts.deps)
        static_packages.add_optional(artifacts.static_packages)
        bootfs_packages.add_optional(artifacts.bootfs_packages)
        bootfs_files.add_optional(artifacts.bootfs_files)
        kernel_cmdline.add_optional(artifacts.kernel_cmdline)

    for file in args.required_assembly_input_bundles:
        aib_path = os.path.dirname(file.name)
        aib = json_load(AssemblyInputBundle, file)

        artifacts = collect_aib_artifacts(aib, aib_path)
        deps.extend(artifacts.deps)
        static_packages.add_required(artifacts.static_packages)
        bootfs_packages.add_required(artifacts.bootfs_packages)
        bootfs_files.add_required(artifacts.bootfs_files)
        kernel_cmdline.add_required(artifacts.kernel_cmdline)

    # Merge in the optional input goldens.
    if args.static_packages_input:
        static_packages.add_optional(args.static_packages_input.readlines())
    if args.bootfs_packages_input:
        bootfs_packages.add_optional(args.bootfs_packages_input.readlines())
    if args.bootfs_files_input:
        bootfs_files.add_optional(args.bootfs_files_input.readlines())
    if args.kernel_args_input:
        kernel_cmdline.add_optional(args.kernel_args_input.readlines())

    with args.static_packages_output as static_packages_output:
        static_packages.write(static_packages_output)

    with args.bootfs_packages_output as bootfs_packages_output:
        bootfs_packages.write(bootfs_packages_output)

    with args.bootfs_files_output as bootfs_files_output:
        bootfs_files.write(bootfs_files_output)

    with args.kernel_cmdline_output as kernel_cmdline_output:
        kernel_cmdline.write(kernel_cmdline_output)

    if args.depfile:
        with args.depfile as depfile:
            DepFile.from_deps(args.static_packages_output.name, deps).write_to(
                depfile
            )

    return 0
