/**
 * @template T
 * @param {Graph<T>} graph
 * @returns {T[][]}
 */
export function graph_compute_disconnected_clusters(graph) {

    // discover disconnected clusters
    const unprocessed = new Set(graph.getNodes());

    /**
     *
     * @type {T[][]}
     */
    const clusters = [];

    while (unprocessed.size > 0) {
        /**
         *
         * @type {T[]}
         */
        const cluster = [];

        const next = unprocessed.values().next().value;

        const open = [next];

        while (open.length > 0) {
            const node = open.pop();

            unprocessed.delete(node);
            cluster.push(node);

            const container = graph.getNodeContainer(node);

            const edges = container.getEdges();

            const edge_count = edges.length;

            for (let i = 0; i < edge_count; i++) {
                const edge = edges[i];

                const neighbour = edge.other(node);

                if (!unprocessed.has(neighbour)) {
                    continue;
                }

                unprocessed.delete(neighbour);

                open.push(neighbour);
            }
        }

        clusters.push(cluster);
    }

    return clusters;
}
