// REVCLOUD command — draw a revision cloud (arc-bumped closed polyline).
//
// Workflow: pick polygon corners (like PLINE), press Enter to close.
// Each segment of the polygon is subdivided into arc bumps (bulge = 0.5).
// Minimum arc length = `arc_length` parameter.

use acadrust::entities::LwPolyline;
use acadrust::types::Vector2;
use acadrust::{entities::LwVertex, EntityType};
use glam::DVec3;

use crate::command::{CadCommand, CmdResult};
use crate::modules::{IconKind, ModuleEvent, ToolDef};
use crate::scene::model::wire_model::WireModel;

pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../../assets/icons/revcloud.svg"));

pub fn tool() -> ToolDef {
    ToolDef {
        id: "REVCLOUD",
        label: "Rev Cloud",
        icon: ICON,
        event: ModuleEvent::Command("REVCLOUD".to_string()),
    }
}

const DEFAULT_ARC_LEN: f64 = 1.0; // default arc bump length

pub struct RevCloudCommand {
    points: Vec<DVec3>,
    arc_length: f64,
}

impl RevCloudCommand {
    pub fn new() -> Self {
        Self {
            points: vec![],
            arc_length: DEFAULT_ARC_LEN,
        }
    }
}

impl CadCommand for RevCloudCommand {
    fn name(&self) -> &'static str {
        "REVCLOUD"
    }

    fn prompt(&self) -> String {
        if self.points.is_empty() {
            format!(
                "REVCLOUD  Specify start point (arc length = {:.2}):",
                self.arc_length
            )
        } else {
            format!(
                "REVCLOUD  Specify next point ({} pts, Enter to close):",
                self.points.len()
            )
        }
    }

    fn on_point(&mut self, pt: DVec3) -> CmdResult {
        self.points.push(pt);
        CmdResult::NeedPoint
    }

    fn on_enter(&mut self) -> CmdResult {
        if self.points.len() < 3 {
            return CmdResult::Cancel;
        }
        let entity = make_revcloud(&self.points, self.arc_length);
        CmdResult::CommitAndExit(entity)
    }

    fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> {
        let pt = pt.as_vec3();
        if self.points.is_empty() {
            return None;
        }
        let mut preview_pts: Vec<[f32; 3]> = self
            .points
            .iter()
            .map(|p| [p.x as f32, p.y as f32, p.z as f32])
            .collect();
        preview_pts.push([pt.x, pt.y, pt.z]);
        preview_pts.push([
            self.points[0].x as f32,
            self.points[0].y as f32,
            self.points[0].z as f32,
        ]);
        Some(WireModel {
            taper_widths: Vec::new(),
            world_width: 0.0,
            depth_override: None,
            fill_is_3d: false,
            pick_tris: Vec::new(),
            pick_tris_low: Vec::new(),
            dash_from_start: false,
            dash_align_end: None,
            text_verts: Vec::new(),
            name: "revcloud_preview".into(),
            points: preview_pts,
            points_low: Vec::new(),
            color: WireModel::CYAN,
            selected: false,
            pattern_length: 0.0,
            pattern: [0.0; 8],
            line_weight_px: 1.0,
            snap_pts: vec![],
            tangent_geoms: vec![],
            aci: 0,
            key_vertices: vec![],
            aabb: WireModel::UNBOUNDED_AABB,
            plinegen: true,
            fill_tris: vec![],
            fill_tris_low: Vec::new(),
        })
    }
}

fn make_revcloud(pts: &[DVec3], arc_len: f64) -> EntityType {
    let n = pts.len();
    let mut vertices: Vec<LwVertex> = Vec::new();

    // For each edge, subdivide into arc bumps (bulge ≈ 0.5)
    let bump_bulge = 0.5f64; // tan(included_angle/4) ≈ 0.5 → ~53° arc

    for i in 0..n {
        let p0 = pts[i];
        let p1 = pts[(i + 1) % n];
        let seg_len = ((p1.x - p0.x).powi(2) + (p1.y - p0.y).powi(2)).sqrt();
        if seg_len < 1e-6 {
            continue;
        }

        // How many full arcs fit?
        let num_arcs = ((seg_len / arc_len).round() as usize).max(1);
        let step_x = (p1.x - p0.x) / num_arcs as f64;
        let step_y = (p1.y - p0.y) / num_arcs as f64;

        for j in 0..num_arcs {
            let x = p0.x + step_x * j as f64;
            let y = p0.y + step_y * j as f64; // DXF Y
            let mut v = LwVertex::new(Vector2::new(x, y));
            v.bulge = bump_bulge;
            vertices.push(v);
        }
    }

    let mut p = LwPolyline::new();
    p.is_closed = true;
    p.vertices = vertices;
    EntityType::LwPolyline(p)
}


// ── Autocomplete registry ─────────────────────────────────
inventory::submit!(crate::command::CommandRegistration { names: &["REVCLOUD"] });  // RevCloudCommand
