from typing import OrderedDict
import copy


def exclude_layer_from_graph(graph, ignore_layers):
    """
    Exclude specific types of layers from the graph.

    Parameters
    ----------
    graph : dict
        Layer graph where each value is a list of layers
        defined in this graph as a key.

    ignore_layers : list or tuple of layers
        Layer types that need to be exclude from the graph.

    Returns
    -------
    dict
        New graph with excluded layers.
    """
    ignore_layers = tuple(ignore_layers)
    cleaned_graph = OrderedDict()

    for from_layer, to_layers in graph.items():
        if isinstance(from_layer, ignore_layers):
            continue

        cleaned_graph[from_layer] = []
        to_layers = copy.copy(to_layers)

        while to_layers:
            to_layer = to_layers.pop()

            if isinstance(to_layer, ignore_layers):
                # from_layer connects to the to_layer that
                # we need to exclude. For this reason we just
                # connect from_layer to layers that connected
                # from the to_layer
                #
                # Before:
                # from_layer -> to_layer -> next_to_layers
                #
                # After:
                # from_layer-> next_to_layers
                to_layers.extend(graph[to_layer])

            else:
                cleaned_graph[from_layer].append(to_layer)

    return cleaned_graph