import itertools
from collections import defaultdict, deque

from ...utils import arbitrary_element, py_random_state
from ...classes.graph import Graph

__all__ = [
    "greedy_color",
    "strategy_connected_sequential",
    "strategy_connected_sequential_bfs",
    "strategy_connected_sequential_dfs",
    "strategy_independent_set",
    "strategy_largest_first",
    "strategy_random_sequential",
    "strategy_saturation_largest_first",
    "strategy_smallest_last",
]

def strategy_largest_first(G: Graph, colors): ...
@py_random_state(2)
def strategy_random_sequential(G: Graph, colors, seed=None): ...
def strategy_smallest_last(G: Graph, colors): ...
def strategy_independent_set(G: Graph, colors): ...
def strategy_connected_sequential_bfs(G: Graph, colors): ...
def strategy_connected_sequential_dfs(G: Graph, colors): ...
def strategy_connected_sequential(G: Graph, colors, traversal="bfs"): ...
def strategy_saturation_largest_first(G: Graph, colors): ...

#: Dictionary mapping name of a strategy as a string to the strategy function.
STRATEGIES: dict = ...

def greedy_color(G: Graph, strategy="largest_first", interchange: bool = False): ...

# Tools for coloring with interchanges
class _Node:
    __slots__: list = ...

    def __init__(self, node_id, n): ...
    def __repr__(self): ...
    def assign_color(self, adj_entry, color): ...
    def clear_color(self, adj_entry, color): ...
    def iter_neighbors(self): ...
    def iter_neighbors_color(self, color): ...

class _AdjEntry:
    __slots__: list = ...

    def __init__(self, node_id): ...
    def __repr__(self): ...
