# Path: regraph/exceptions.py
# class ReGraphError(ReGraphException):
#     """Exception for errors in ReGraph."""
# 
# class RewritingError(ReGraphException):
#     """Exceptions class for errors in rewriting in a hierarchy."""
# 
# class HierarchyError(ReGraphException):
#     """Exceptions class for hierarchy handling."""
# 
# class InvalidHomomorphism(ReGraphException):
#     """Exceptions class for invalid homomorphisms."""
# 
# Path: regraph/utils.py
# def keys_by_value(dictionary, val):
#     """Get keys of a dictionary by a value."""
#     res = []
#     for key, value in dictionary.items():
#         if value == val:
#             res.append(key)
#     return res
# 
# def format_typing(typing):
#     if typing is None:
#         typing = dict()
#     new_typing = dict()
#     for key, value in typing.items():
#         if type(value) == dict:
#             new_typing[key] = copy.deepcopy(value)
#         else:
#             try:
#                 if len(value) == 2:
#                     new_typing[key] = copy.deepcopy(value)
#                 elif len(value) == 1:
#                     new_typing[key] = copy.deepcopy(value[0])
#             except:
#                 raise ReGraphError("Typing format is not valid!")
#     return new_typing
# 
# def normalize_typing_relation(typing_rel):
#     new_typing_rel = format_typing(typing_rel)
#     for g, typing_rel in new_typing_rel.items():
#         for key, values in typing_rel.items():
#             value_set = set()
#             if type(values) == str:
#                 value_set.add(values)
#             else:
#                 try:
#                     for v in values:
#                         value_set.add(v)
#                 except TypeError:
#                     value_set.add(values)
#             if len(value_set) > 0:
#                 new_typing_rel[g][key] = value_set
#     return new_typing_rel


import networkx as nx
from networkx.exception import NetworkXNoPath
from regraph.exceptions import (ReGraphError,
                                RewritingError,
                                HierarchyError,
                                InvalidHomomorphism)
from regraph.utils import (keys_by_value,
                           format_typing,
                           normalize_typing_relation)
from regraph.networkx.category_utils import (check_homomorphism,
                                             compose,
                                             is_monic)
                    )

                # find homomorphisms from s to t via other paths
                s_t_paths = nx.all_shortest_paths(hierarchy, s, t)
                try:
                    # check only the first path
                    for path in s_t_paths:
                        path_homomorphism = hierarchy.compose_path_typing(path)
                        if path_homomorphism != new_homomorphism:
                            raise HierarchyError(
                                "Homomorphism does not commute with an " +
                                "existing path from '%s' to '%s'!" % (s, t)
                            )
                except(nx.NetworkXNoPath):
                        pass


def _autocomplete_typing(hierarchy, graph_id, instance,
                         lhs_typing, p_typing, rhs_typing_rel, p_lhs, p_rhs):
    if lhs_typing is None:
        new_lhs_typing = dict()
    else:
        new_lhs_typing = format_typing(lhs_typing)
    if p_typing is None:
        new_p_typing = dict()
    else:
        new_p_typing = normalize_typing_relation(p_typing)
    if rhs_typing_rel is None:
        new_rhs_typing_rel = dict()
    else:

# Path: regraph/exceptions.py
# class ReGraphError(ReGraphException):
#     """Exception for errors in ReGraph."""
# 
# class RewritingError(ReGraphException):
#     """Exceptions class for errors in rewriting in a hierarchy."""
# 
# class HierarchyError(ReGraphException):
#     """Exceptions class for hierarchy handling."""
# 
# class InvalidHomomorphism(ReGraphException):
#     """Exceptions class for invalid homomorphisms."""
# 
# Path: regraph/utils.py
# def keys_by_value(dictionary, val):
#     """Get keys of a dictionary by a value."""
#     res = []
#     for key, value in dictionary.items():
#         if value == val:
#             res.append(key)
#     return res
# 
# def format_typing(typing):
#     if typing is None:
#         typing = dict()
#     new_typing = dict()
#     for key, value in typing.items():
#         if type(value) == dict:
#             new_typing[key] = copy.deepcopy(value)
#         else:
#             try:
#                 if len(value) == 2:
#                     new_typing[key] = copy.deepcopy(value)
#                 elif len(value) == 1:
#                     new_typing[key] = copy.deepcopy(value[0])
#             except:
#                 raise ReGraphError("Typing format is not valid!")
#     return new_typing
# 
# def normalize_typing_relation(typing_rel):
#     new_typing_rel = format_typing(typing_rel)
#     for g, typing_rel in new_typing_rel.items():
#         for key, values in typing_rel.items():
#             value_set = set()
#             if type(values) == str:
#                 value_set.add(values)
#             else:
#                 try:
#                     for v in values:
#                         value_set.add(v)
#                 except TypeError:
#                     value_set.add(values)
#             if len(value_set) > 0:
#                 new_typing_rel[g][key] = value_set
#     return new_typing_rel


# Path: regraph/backends/networkx/utils/type_checking.py
import networkx as nx
from networkx.exception import NetworkXNoPath
from regraph.exceptions import (ReGraphError,
                                RewritingError,
                                HierarchyError,
                                InvalidHomomorphism)
from regraph.utils import (keys_by_value,
                           format_typing,
                           normalize_typing_relation)
from regraph.networkx.category_utils import (check_homomorphism,
                                             compose,
                                             is_monic)

                    )

                # find homomorphisms from s to t via other paths
                s_t_paths = nx.all_shortest_paths(hierarchy, s, t)
                try:
                    # check only the first path
                    for path in s_t_paths:
                        path_homomorphism = hierarchy.compose_path_typing(path)
                        if path_homomorphism != new_homomorphism:
                            raise HierarchyError(
                                "Homomorphism does not commute with an " +
                                "existing path from '%s' to '%s'!" % (s, t)
                            )
                except(nx.NetworkXNoPath):
                        pass


def _autocomplete_typing(hierarchy, graph_id, instance,
                         lhs_typing, p_typing, rhs_typing_rel, p_lhs, p_rhs):
    if lhs_typing is None:
        new_lhs_typing = dict()
    else:
        new_lhs_typing = format_typing(lhs_typing)
    if p_typing is None:
        new_p_typing = dict()
    else:
        new_p_typing = normalize_typing_relation(p_typing)
    if rhs_typing_rel is None:
        new_rhs_typing_rel = dict()
    else:

        new_rhs_typing_rel = normalize_typing_relation(rhs_typing_rel)