use std::{
    fs::File,
    io::{BufReader, BufWriter},
};

use bincode::Options;
use dyntri_cdt2d::monte_carlo::fixed_volume::Simulation;
use dyntri_core::graph::observables::bfs::bfs_sphere_volumes;
use rand::SeedableRng;
use rand_xoshiro::Xoshiro128StarStar;

const NUM_TRIANGLES: usize = 5000;
const NTIME: u16 = 25;
const NUM_SWEEPS: f64 = 50.0;

fn main() {
    // Setup RNG
    let mut rng = Xoshiro128StarStar::seed_from_u64(42);
    // Initialize simulation
    let mut simulation = Simulation::default(NUM_TRIANGLES, NTIME);

    // Perform simulation
    let sweep = NUM_TRIANGLES as f64;
    for _ in 0..((sweep * NUM_SWEEPS) as usize) {
        simulation.step(&mut rng);
    }

    // Store simulator state in a file for later use
    let file = File::create("simulation.dat").expect("Could not create file");
    bincode::DefaultOptions::new()
        .serialize_into(BufWriter::new(file), &simulation)
        .expect("Saving simulation state to file failed");

    // Load simulator state from file as example
    let file = File::open("simulation.dat").expect("Could not open simulation file");
    let simulation: Simulation = bincode::DefaultOptions::new()
        .deserialize_from(BufReader::new(file))
        .expect("Could not load simulation state from file");

    // Reconstruct full triangulation information
    let triangulation = simulation.construct_triangulation();
    // Reconstruct vertex graph
    let graph = triangulation.vertex_graph();
    // Take measurement, e.g. sphere shell profile
    let volume_profile = bfs_sphere_volumes(&graph, 0, 30);
    println!("Volume profile: {volume_profile:?}");
}
