// DIMTEDIT command — reposition the text of an existing dimension.
//
// Workflow:
//   1. Pick a dimension entity
//   2. Click the new text position (entity data is injected by update.rs after pick)

use acadrust::{EntityType, Handle};
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/dim_tedit.svg"));

pub fn tool() -> ToolDef {
    ToolDef {
        id: "DIMTEDIT",
        label: "Dim Text Edit",
        icon: ICON,
        event: ModuleEvent::Command("DIMTEDIT".to_string()),
    }
}

enum Step {
    PickDim,
    PickTextPos {
        handle: Handle,
        entity: Option<EntityType>,
    },
}

pub struct DimTeditCommand {
    step: Step,
}

impl DimTeditCommand {
    pub fn new() -> Self {
        Self {
            step: Step::PickDim,
        }
    }
}

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

    fn prompt(&self) -> String {
        match &self.step {
            Step::PickDim => "DIMTEDIT  Select dimension:".into(),
            Step::PickTextPos { .. } => "DIMTEDIT  Specify new location for dimension text:".into(),
        }
    }

    fn needs_entity_pick(&self) -> bool {
        matches!(self.step, Step::PickDim)
    }

    fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
        if handle.is_null() {
            return CmdResult::NeedPoint;
        }
        self.step = Step::PickTextPos {
            handle,
            entity: None,
        };
        CmdResult::NeedPoint
    }

    fn on_point(&mut self, pt: DVec3) -> CmdResult {
        if let Step::PickTextPos { handle, entity } = &mut self.step {
            let h = *handle;
            if let Some(mut ent) = entity.take() {
                if let EntityType::Dimension(ref mut d) = ent {
                    let new_pt = acadrust::types::Vector3::new(pt.x, pt.y, pt.z);
                    d.base_mut().text_middle_point = new_pt;
                    d.base_mut().insertion_point = new_pt;
                    // Pin the text to this location, else the renderer recomputes
                    // the style-default placement and the move is discarded.
                    d.base_mut().text_user_positioned = true;
                }
                return CmdResult::ReplaceEntity(h, vec![ent]);
            }
            // No entity yet — wait for inject
            CmdResult::NeedPoint
        } else {
            CmdResult::NeedPoint
        }
    }

    fn on_enter(&mut self) -> CmdResult {
        CmdResult::Cancel
    }

    fn on_mouse_move(&mut self, pt: DVec3) -> Option<WireModel> { let pt = pt.as_vec3();
        if !matches!(self.step, Step::PickTextPos { .. }) {
            return None;
        }
        let d = 0.2_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: "dimtedit_preview".into(),
            // Marker box in the XY drawing plane (Z is elevation, ~0). The old
            // box varied Z, so in the top-down view it collapsed to a flat line
            // instead of a square. (#150)
            points: vec![
                [pt.x - d, pt.y - d, pt.z],
                [pt.x + d, pt.y - d, pt.z],
                [pt.x + d, pt.y + d, pt.z],
                [pt.x - d, pt.y + d, pt.z],
                [pt.x - d, pt.y - d, pt.z],
            ],
            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 inject_picked_entity(&mut self, entity: EntityType) {
        if let Step::PickTextPos { entity: slot, .. } = &mut self.step {
            *slot = Some(entity);
        }
    }
}


// ── Autocomplete registry ─────────────────────────────────
inventory::submit!(crate::command::CommandRegistration { names: &["DIMTED", "DIMTEDIT"] });  // DimTeditCommand
