import { fm_kway } from "./fm_kway.js";
import { project_kway } from "./project_kway.js";

/**
 * Uncoarsen the multilevel graph hierarchy, running FM refinement at every level.
 *
 * On entry, `coarsest_graph` has a valid initial partition in
 * `coarsest_graph.vertex_partition[]` and its refinement bookkeeping fully
 * populated (via `compute_kway_params`). On exit, `original_graph.vertex_partition[]`
 * holds the refined partition of the original finest graph.
 *
 * Mirrors `RefineKWay` from libmetis/kwayrefine.c, simplified:
 *   - no minconn / contig handling
 *   - no separate balance passes (we run REFINE-only at each level; the
 *     adaptive ub_factor in fm_kway recovers most of what an explicit BALANCE
 *     pass would have done)
 *   - no separator/volume code
 *
 * @param {import('../MetisGraph.js').MetisGraph} original_graph the finest graph
 * @param {import('../MetisGraph.js').MetisGraph} coarsest_graph the coarsest graph
 * @param {number} partition_count
 * @param {{
 *   random: function():number,
 *   pass_count?: number,
 *   ub_factor?: number,
 *   fudge_factor?: number,
 * }} opts forwarded to `fm_kway`
 * @param {import('./RefinementScratch.js').RefinementScratch} scratch shared scratch
 *   sized to `original_graph.vertex_count`
 */
export function refine_kway(original_graph, coarsest_graph, partition_count, opts, scratch) {
    let current_level = coarsest_graph;

    // First refine the freshly-initialised coarsest partition before projection.
    fm_kway(current_level, partition_count, opts, scratch);

    while (current_level !== original_graph) {
        const finer_level = current_level.finer_graph;
        project_kway(finer_level, partition_count);
        current_level = finer_level;
        fm_kway(current_level, partition_count, opts, scratch);
    }
}
