use std::alloc::System;
use std::hint::black_box;
use std::time::Instant;

use libremetaverse_prim_mesher::{PathType, PrimMesh};
use stats_alloc::{INSTRUMENTED_SYSTEM, Region, StatsAlloc};

#[global_allocator]
static ALLOCATOR: &StatsAlloc<System> = &INSTRUMENTED_SYSTEM;

fn main() {
    let mut mesh = PrimMesh::new(128, 0.03, 0.97, 0.35, 64)
        .expect("large benchmark profile must fit the documented bounds");
    mesh.viewer_mode = true;
    mesh.calc_vertex_normals = true;
    mesh.path_cut_begin = 0.02;
    mesh.path_cut_end = 0.98;
    mesh.hole_size_x = 0.7;
    mesh.hole_size_y = 0.3;
    mesh.twist_begin = -45;
    mesh.twist_end = 270;
    mesh.taper_x = 0.15;
    mesh.taper_y = -0.1;
    mesh.skew = 0.2;
    mesh.radius = 0.1;
    mesh.revolutions = 1.5;
    mesh.steps_per_revolution = 96;

    let allocation_region = Region::new(ALLOCATOR);
    let started = Instant::now();
    mesh.extrude(PathType::Circular)
        .expect("bounded circular extrusion");
    let indexer = mesh
        .get_vertex_indexer()
        .expect("checked viewer indexing")
        .expect("viewer-mode indexer");
    let elapsed = started.elapsed();
    let allocation_stats = allocation_region.change();

    assert!(!mesh.coords.is_empty());
    assert!(!mesh.faces.is_empty());
    assert!(!mesh.viewer_faces.is_empty());
    assert!(mesh.viewer_faces.len() <= mesh.faces.len());
    black_box((&mesh, &indexer));
    println!(
        "meshing pipeline: {} coordinates, {} triangles, {} prim faces in {elapsed:?}, {} allocations, {} reallocations, {} bytes allocated",
        mesh.coords.len(),
        mesh.faces.len(),
        indexer.num_prim_faces,
        allocation_stats.allocations,
        allocation_stats.reallocations,
        allocation_stats.bytes_allocated,
    );
}
