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

"""Generates pretty dependency graphs for Chrome OS packages."""

import json
import os
import sys

from chromite.lib import commandline
from chromite.lib import dot_helper


NORMAL_COLOR = "black"
TARGET_COLOR = "red"
SEED_COLOR = "green"
CHILD_COLOR = "grey"


def GetReverseDependencyClosure(full_name, deps_map):
    """Gets the closure of the reverse dependencies of a node.

    Walks the tree along all the reverse dependency paths to find all the nodes
    that transitively depend on the input node.
    """
    s = set()

    def GetClosure(name) -> None:
        s.add(name)
        node = deps_map[name]
        for dep in node["rev_deps"]:
            if dep in s:
                continue
            GetClosure(dep)

    GetClosure(full_name)
    return s


def GetOutputBaseName(node, options):
    """Gets the basename of the output file for a node."""
    return "%s_%s-%s.%s" % (
        node["category"],
        node["name"],
        node["version"],
        options.format,
    )


def AddNodeToSubgraph(subgraph, node, options, color) -> None:
    """Gets the dot definition for a node."""
    name = node["full_name"]
    href = None
    if options.link:
        filename = GetOutputBaseName(node, options)
        href = "%s%s" % (options.base_url, filename)
    subgraph.AddNode(name, name, color, href)


def GenerateDotGraph(package, deps_map, options):
    """Generates the dot source for the dependency graph leading to a node.

    The output is a list of lines.
    """
    deps = GetReverseDependencyClosure(package, deps_map)
    node = deps_map[package]

    # Keep track of all the emitted nodes so that we don't issue multiple
    # definitions
    emitted = set()

    graph = dot_helper.Graph(package)

    # Add all the children if we want them, all of them in their own subgraph,
    # as a sink. Keep the arcs outside of the subgraph though (it generates
    # better layout).
    children_subgraph = None
    if options.children and node["deps"]:
        children_subgraph = graph.AddNewSubgraph("sink")
        for child in node["deps"]:
            child_node = deps_map[child]
            AddNodeToSubgraph(
                children_subgraph, child_node, options, CHILD_COLOR
            )
            emitted.add(child)
            graph.AddArc(package, child)

    # Add the package in its own subgraph. If we didn't have children, make it
    # a sink
    if children_subgraph:
        rank = "same"
    else:
        rank = "sink"
    package_subgraph = graph.AddNewSubgraph(rank)
    AddNodeToSubgraph(package_subgraph, node, options, TARGET_COLOR)
    emitted.add(package)

    # Add all the other nodes, as well as all the arcs.
    for dep in deps:
        dep_node = deps_map[dep]
        if not dep in emitted:
            color = NORMAL_COLOR
            if dep_node["action"] == "seed":
                color = SEED_COLOR
            AddNodeToSubgraph(graph, dep_node, options, color)
        for j in dep_node["rev_deps"]:
            graph.AddArc(j, dep)

    return graph.Gen()


def GenerateImages(data, options) -> None:
    """Generate the output images for all the nodes in the input."""
    deps_map = json.loads(data)

    for package in deps_map:
        lines = GenerateDotGraph(package, deps_map, options)

        filename = os.path.join(
            options.output_dir, GetOutputBaseName(deps_map[package], options)
        )

        save_dot_filename = None
        if options.save_dot:
            save_dot_filename = filename + ".dot"

        dot_helper.GenerateImage(
            lines, filename, options.format, save_dot_filename
        )


def GetParser():
    """Return a command line parser."""
    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "-f",
        "--format",
        default="svg",
        help="Dot output format (png, svg, etc.).",
    )
    parser.add_argument(
        "-o", "--output-dir", default=".", help="Output directory."
    )
    parser.add_argument(
        "-c", "--children", action="store_true", help="Also add children."
    )
    parser.add_argument(
        "-l", "--link", action="store_true", help="Embed links."
    )
    parser.add_argument(
        "-b", "--base-url", default="", help="Base url for links."
    )
    parser.add_argument(
        "-s", "--save-dot", action="store_true", help="Save dot files."
    )
    parser.add_argument("inputs", nargs="*", help="Chromium OS package lists")
    return parser


def main(argv) -> None:
    parser = GetParser()
    options = parser.parse_args(argv)
    options.Freeze()

    try:
        os.makedirs(options.output_dir)
    except OSError:
        # The directory already exists.
        pass

    if not options.inputs:
        GenerateImages(sys.stdin.read(), options)
    else:
        for i in options.inputs:
            with open(i, encoding="utf-8") as handle:
                GenerateImages(handle.read(), options)
