# Copyright 2019 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""The Package Size Reporting CLI entry point."""

import os

from chromite.lib import commandline
from chromite.lib import metrics_lib
from chromite.lib import portage_util
from chromite.utils import pformat


_PARTITION_NAMES = ["rootfs", "stateful"]


def _get_parser():
    """Create an argument parser for this script."""
    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--root",
        required=True,
        type="str_path",
        help="Specify the rootfs to investigate.",
    )
    parser.add_argument(
        "--image-type",
        help="Specify the type of image being investigated. "
        "e.g. [base, dev, test]",
    )
    parser.add_argument(
        "--partition-name",
        choices=_PARTITION_NAMES,
        help="Specify the partition name. " "e.g. [rootfs, stateful]",
    )
    parser.add_argument(
        "packages",
        nargs="*",
        help="Names of packages to investigate. Must be "
        "specified as category/package-version.",
    )
    return parser


def generate_package_size_report(
    db, root, image_type, partition_name, installed_packages
):
    """Collect package sizes and generate a report."""
    results = {}
    package_sizes = portage_util.GeneratePackageSizes(
        db, root, installed_packages
    )
    timestamp = metrics_lib.current_milli_time()
    for package_cpv, size in package_sizes:
        results[package_cpv] = size
        metrics_lib.append_metrics_log(
            timestamp,
            "package_size.%s.%s.%s" % (image_type, partition_name, package_cpv),
            metrics_lib.OP_GAUGE,
            arg=size,
        )

    rootfs_stat = os.statvfs(root)
    block_size = rootfs_stat.f_bsize
    blocks_used = rootfs_stat.f_blocks - rootfs_stat.f_bfree
    total_size = block_size * blocks_used

    metrics_lib.append_metrics_log(
        timestamp,
        "total_size.%s.%s" % (image_type, partition_name),
        metrics_lib.OP_GAUGE,
        arg=total_size,
    )
    return {
        "root": root,
        "package_sizes": results,
        "total_size": total_size,
        "package_database_path": db.db_path,
        "package_install_path": db.package_install_path,
    }


def main(argv) -> None:
    """Find and report approximate size info for a particular built package."""
    commandline.RunInsideChroot()

    parser = _get_parser()
    opts = parser.parse_args(argv)
    opts.Freeze()

    vdb = package_install_path = ""
    if opts.partition_name == "stateful":
        vdb = "var_overlay/db/pkg"
        package_install_path = "dev_image"
    db = portage_util.PortageDB(
        root=opts.root, vdb=vdb, package_install_path=package_install_path
    )

    if opts.packages:
        installed_packages = portage_util.GenerateInstalledPackages(
            db, opts.root, opts.packages
        )
    else:
        installed_packages = db.InstalledPackages()

    results = generate_package_size_report(
        db, opts.root, opts.image_type, opts.partition_name, installed_packages
    )
    print(pformat.json(results))
