//! Count distinct *partitions* (label-invariant) in a BEN file.
//!
//! Each accepted frame's assignment is canonicalized by relabeling districts
//! in order of first appearance, then hashed with xxh3-128. Plans that differ
//! only by a permutation of district labels collide on the same digest and
//! thus count as the same partition.

use crate::metrics::canonical::canonical_hash;
use crate::pipeline::{count_samples, run_pipeline};
use std::collections::HashSet;
use std::fs::File;
use std::io::Write;

pub fn count_and_save_unique_plans(
    in_file_name: &str,
    out_file_name: &str,
    show_progress: bool,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
    let total = count_samples(in_file_name)?;

    let mut unique: HashSet<u128> = HashSet::new();
    let mut total_frames: u64 = 0;

    run_pipeline(
        in_file_name,
        total,
        |assignment, _n_reps| canonical_hash(assignment),
        |_step, _n_reps, _accepted, hash| {
            unique.insert(hash);
            total_frames += 1;
        },
        show_progress,
    )?;

    let n_unique = unique.len();
    eprintln!(
        "Unique plans: {} (out of {} accepted frames)",
        n_unique, total_frames
    );

    let mut out = File::create(out_file_name)?;
    writeln!(out, "unique_plans: {}", n_unique)?;
    writeln!(out, "total_accepted_frames: {}", total_frames)?;

    eprintln!("Wrote {}", out_file_name);
    Ok(())
}
