pub(crate) mod analysis;
pub(crate) mod astar;
pub(crate) mod clipping;
pub(crate) mod cylindrical;
pub(crate) mod engagement;
pub(crate) mod fillet;
pub(crate) mod fitting;
pub(crate) mod helix;
pub(crate) mod hull;
pub(crate) mod interp;
pub(crate) mod intersect;
pub(crate) mod medial_axis;
pub(crate) mod minkowski2d;
pub(crate) mod narrow;
pub(crate) mod nest2d;
pub(crate) mod offset;
pub(crate) mod ordering;
pub(crate) mod overcut;
pub(crate) mod polylabel;
pub(crate) mod ramp;
pub(crate) mod rootfind;
pub(crate) mod simplify;
pub(crate) mod smooth;
pub(crate) mod spatial_grid2d;
pub(crate) mod spiral;
pub(crate) mod trochoid;

pyo3_stub_gen::module_doc!("raygeo.geo.algo", "{}", MODULE_DOC);

pub(crate) const MODULE_DOC: &str = "\
Geometric algorithms for path processing.

This module provides algorithms that operate on geometry paths and point
sequences. It covers several categories of geometric processing:

Clipping — intersect and clip line segments against rectangles and
polygon regions. Also includes coordinate conversion between floating
point and Clipper's integer grid system for boolean-accuracy clipping.

Fitting — reconstruct curves (arcs, lines, beziers) from unordered
point sequences. Includes recursive primitive fitting, circle fitting,
polyline linearization, and deviation analysis to evaluate fit quality.

Minkowski sums — compute Minkowski sums, convolutions, and no-fit
polygons for 2D toolpath generation, nesting, and packing algorithms.

Nesting — 2D packing algorithms for sheet/plate layout (NFP, IFP,
placement, gravity, genetic optimization).

Simplification — reduce the number of points in a polyline while
preserving shape within a tolerance (Ramer-Douglas-Peucker).

Smoothing — apply Gaussian kernel smoothing to polylines with
configurable corner-angle thresholds to preserve sharp features.
";

use pyo3::prelude::*;

pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
    let py = m.py();
    let algo_mod = PyModule::new(py, "algo")?;
    algo_mod.setattr("__doc__", MODULE_DOC)?;

    analysis::register(&algo_mod)?;
    astar::register(&algo_mod)?;
    clipping::register(&algo_mod)?;
    cylindrical::register(&algo_mod)?;
    engagement::register(&algo_mod)?;
    fillet::register(&algo_mod)?;
    fitting::register(&algo_mod)?;
    helix::register(&algo_mod)?;
    hull::register(&algo_mod)?;
    medial_axis::register(&algo_mod)?;
    interp::register(&algo_mod)?;
    intersect::register(&algo_mod)?;
    minkowski2d::register(&algo_mod)?;
    narrow::register(&algo_mod)?;
    nest2d::register(&algo_mod)?;
    offset::register(&algo_mod)?;
    ordering::register(&algo_mod)?;
    overcut::register(&algo_mod)?;
    polylabel::register(&algo_mod)?;
    ramp::register(&algo_mod)?;
    rootfind::register(&algo_mod)?;
    simplify::register(&algo_mod)?;
    smooth::register(&algo_mod)?;
    spatial_grid2d::register(&algo_mod)?;
    spiral::register(&algo_mod)?;
    trochoid::register(&algo_mod)?;

    m.add_submodule(&algo_mod)?;

    let sys_modules = py.import("sys")?.getattr("modules")?;
    sys_modules.set_item("raygeo.geo.algo", &algo_mod)?;
    sys_modules
        .set_item("raygeo.geo.algo.analysis", &algo_mod.getattr("analysis")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.astar", &algo_mod.getattr("astar")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.clipping", &algo_mod.getattr("clipping")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.fillet", &algo_mod.getattr("fillet")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.fitting", &algo_mod.getattr("fitting")?)?;
    sys_modules.set_item("raygeo.geo.algo.hull", &algo_mod.getattr("hull")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.interp", &algo_mod.getattr("interp")?)?;
    sys_modules.set_item(
        "raygeo.geo.algo.intersect",
        &algo_mod.getattr("intersect")?,
    )?;
    sys_modules
        .set_item("raygeo.geo.algo.nest2d", &algo_mod.getattr("nest2d")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.offset", &algo_mod.getattr("offset")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.ordering", &algo_mod.getattr("ordering")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.overcut", &algo_mod.getattr("overcut")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.simplify", &algo_mod.getattr("simplify")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.smooth", &algo_mod.getattr("smooth")?)?;
    sys_modules.set_item(
        "raygeo.geo.algo.spatial_grid2d",
        &algo_mod.getattr("spatial_grid2d")?,
    )?;
    sys_modules.set_item(
        "raygeo.geo.algo.engagement",
        &algo_mod.getattr("engagement")?,
    )?;
    sys_modules.set_item(
        "raygeo.geo.algo.cylindrical",
        &algo_mod.getattr("cylindrical")?,
    )?;
    sys_modules
        .set_item("raygeo.geo.algo.helix", &algo_mod.getattr("helix")?)?;
    sys_modules.set_item(
        "raygeo.geo.algo.medial_axis",
        &algo_mod.getattr("medial_axis")?,
    )?;
    sys_modules.set_item(
        "raygeo.geo.algo.minkowski2d",
        &algo_mod.getattr("minkowski2d")?,
    )?;
    sys_modules
        .set_item("raygeo.geo.algo.narrow", &algo_mod.getattr("narrow")?)?;
    sys_modules.set_item(
        "raygeo.geo.algo.polylabel",
        &algo_mod.getattr("polylabel")?,
    )?;
    sys_modules.set_item("raygeo.geo.algo.ramp", &algo_mod.getattr("ramp")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.rootfind", &algo_mod.getattr("rootfind")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.spiral", &algo_mod.getattr("spiral")?)?;
    sys_modules
        .set_item("raygeo.geo.algo.trochoid", &algo_mod.getattr("trochoid")?)?;

    Ok(())
}
