# 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)
                # node will be merged
                all_untyped = True
                for p_node in p_nodes:
                    if instance[rule.p_lhs[p_node]] in typing.keys():
                        all_untyped = False
                        break
                if all_untyped:
                    continue

            if typing_graph in rhs_typing.keys() and\
               node in rhs_typing[typing_graph].keys():
                continue
            else:
                raise RewritingError(
                    "Rewriting is strict (no propagation of types is "
                    "allowed), typing of the node `%s` "
                    "in rhs is required (typing by the following "
                    "graph stays unresolved: '%s')!" %
                    (node, typing_graph))


def _check_instance(hierarchy, graph_id, pattern, instance, pattern_typing):
    # Check that the homomorphism is valid
    try:
        check_homomorphism(
            pattern,
            hierarchy.get_graph(graph_id),
            instance,
            total=True
        )

# 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)

                # node will be merged
                all_untyped = True
                for p_node in p_nodes:
                    if instance[rule.p_lhs[p_node]] in typing.keys():
                        all_untyped = False
                        break
                if all_untyped:
                    continue

            if typing_graph in rhs_typing.keys() and\
               node in rhs_typing[typing_graph].keys():
                continue
            else:
                raise RewritingError(
                    "Rewriting is strict (no propagation of types is "
                    "allowed), typing of the node `%s` "
                    "in rhs is required (typing by the following "
                    "graph stays unresolved: '%s')!" %
                    (node, typing_graph))


def _check_instance(hierarchy, graph_id, pattern, instance, pattern_typing):
    # Check that the homomorphism is valid
    try:
        check_homomorphism(
            pattern,
            hierarchy.get_graph(graph_id),
            instance,
            total=True
        )

    except InvalidHomomorphism as e: