# Copyright 2022 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Implementation for managing a group of JavaClass nodes."""

import collections
from typing import Set, Tuple

import class_dependency
import graph
import group_json_consts


class JavaGroup(graph.Node):
    """A representation of a group of classes."""

    def __init__(self, group_name: str):
        """Initializes a new Java group structure.

        Args:
            group_name: The name of this group.
        """
        super().__init__(group_name)

        self._classes = {}
        self._class_dependency_edges = collections.defaultdict(set)

    @property
    def classes(self):
        """A map { name -> JavaClass } of classes within this group."""
        return self._classes

    def add_class(self, java_class: class_dependency.JavaClass):
        """Adds a JavaClass to the group, if its key doesn't already exist.

        Notably, this does /not/ automatically update the inbound/outbound
        dependencies of the group with the dependencies of the class.
        """
        if java_class.name not in self._classes:
            self._classes[java_class.name] = java_class

    def add_class_dependency_edge(
        self,
        end_group: 'JavaGroup',
        begin_class: class_dependency.JavaClass,
        end_class: class_dependency.JavaClass,
    ):
        """Adds a class dependency edge as part of a group dependency.

        Each group dependency is comprised of one or more class dependencies,
        we manually update the nodes with this info when parsing class graphs.

        Args:
            end_group: the end node of the group dependency edge which starts
                from this node.
            begin_class: the start node of the class dependency edge.
            end_class: the end node of the class dependency edge.
        """
        class_edge = (begin_class, end_class)
        if class_edge not in self._class_dependency_edges[end_group]:
            self._class_dependency_edges[end_group].add(class_edge)

    def get_class_dependencies_in_outbound_edge(
        self, end_node: 'JavaGroup'
    ) -> Set[Tuple]:
        """Breaks down a group dependency edge into class dependencies.

        For group A to depend on another group B, there must exist at least one
        class in A depending on a class in B. This method, given a group
        dependency edge A -> B, returns a set of class dependency edges
        satisfying (class in A) -> (class in B).

        Args:
            end_node: The destination node. This method will return the class
                dependencies forming the edge from the current node to end_node.

        Returns:
            A set of tuples of `JavaClass` nodes, where a tuple (a, b)
            indicates a class dependency a -> b. If there are no relevant
            class dependencies, returns an empty set.
        """
        return self._class_dependency_edges[end_node]

    def get_node_metadata(self):
        """Generates JSON metadata for the current node.

        The list of classes is sorted in order to help with testing.
        Structure:
        {
            'classes': [ class_key, ... ],
        }
        """
        return {
            group_json_consts.CLASSES: sorted(self.classes.keys()),
        }
