# -*- coding: utf-8 -*-
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Command to visualize dependency tree for a given package."""

import sys
from typing import List, Dict

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import depgraph

from . import visualize

_DEFAULT_PACKAGES = ['virtual/target-os', 'virtual/target-os-dev',
                     'virtual/target-os-test', 'virtual/target-os-factory']

def ParseArgs(argv):
  """Parse command line arguments."""
  parser = commandline.ArgumentParser(description=__doc__)
  target = parser.add_mutually_exclusive_group(required=True)
  target.add_argument('--sysroot', type='path', help='Path to the sysroot.')
  target.add_argument('-b', '--build-target', help='Name of the target build')
  parser.add_argument('--output-path', default=None,
                      help='Write output to the given path.')
  parser.add_argument('--output-name', default='DepGraph',
                      help='Write output file name.')
  parser.add_argument('--include-histograms', default=False,
                      help='Create and save histograms about dependencies.')
  parser.add_argument('pkgs', nargs='*', default=_DEFAULT_PACKAGES)
  opts = parser.parse_args(argv)
  opts.Freeze()
  return opts


def CreateRuntimeTree(sysroot: str, pkg_list: str) -> Dict[str, List[str]]:
  """Calculate all packages that are RDEPENDS.

  Use the dependency information about packages to build a tree
  of only RDEPEDS packages and dependencies.

  Args:
    sysroot: The path to the root directory into which the package is
      pretend to be merged. This value is also used for setting
      PORTAGE_CONFIGROOT.
    pkg_list: The list of packages to extract their dependencies from.

  Returns:
    Returns a dictionary of runtime packages with their immediate dependencies.
  """

  # Setup for dependency extraction.
  lib_argv = ['--quiet', '--pretend', '--emptytree']
  lib_argv += ['--sysroot=%s' % sysroot]
  lib_argv.extend(pkg_list)
  dep_graph = depgraph.DepGraphGenerator()
  dep_graph.Initialize(lib_argv)
  deps_tree, _deps_info, _bdeps_tree = dep_graph.GenDependencyTree()

  # Portage returns nothing if the packages given had no dependencies.
  # In those cases we add the given packages so that the output file has
  # something and doesn't appear broken.
  if deps_tree:
    runtime_tree = {pkg: deps_tree[pkg]['deps'].keys() for pkg in deps_tree}
  else:
    runtime_tree = {pkg: [] for pkg in pkg_list}


  return runtime_tree


def main():
  opts = ParseArgs(sys.argv[1:])
  sysroot = opts.sysroot or cros_build_lib.GetSysroot(opts.build_target)
  out_dir = opts.output_path or '.'
  out_name = opts.output_name
  runtime_tree = CreateRuntimeTree(sysroot, opts.pkgs)
  dep_vis = visualize.DepVisualizer(runtime_tree)
  dep_vis.VisualizeGraph(output_name=out_name, output_dir=out_dir)
  if opts.include_histograms:
    dep_vis.GenerateHistograms(opts.build_target, out_dir)
