import itertools
from typing import List, Dict, Tuple, Any
from networkx import Graph


class UserGraphGenerator:

    def __init__(self):
        pass

    def count_edges(self, nodes: List) -> Dict[Tuple, int]:
        edge_counts = {}

        coms = itertools.combinations(nodes, 2)
        for first, second in coms:
            if first == second:  # dont process reflexive connections
                continue

            if (first, second) in edge_counts:
                edge_counts[first, second] += 1
            else:
                edge_counts[first, second] = 1

        return edge_counts

    def create_edges_with_weights(self, edge_counts: Dict[Tuple[Any, Any], int]) -> List[Tuple[Any, Any, Dict]]:
        edges = []
        for (key1, key2), value in edge_counts.items():
            edge = (key1, key2, {'weight': value})
            edges.append(edge)

        return edges

    def create_fully_connected_edges_for_nodes(self, nodes: List) -> List[Tuple[Any, Any, Dict]]:
        return self.create_edges_with_weights(self.count_edges(nodes))

    def create_graph_from_nodes(self, nodes: List) -> Graph:
        '''Creates a networkx.Graph with distinct nodes and weighted edges between these nodes'''
        g = Graph()
        g.add_nodes_from(nodes)
        g.add_edges_from(self.create_fully_connected_edges_for_nodes(nodes))
        return g
