/// Tool system for the toolbar
///
/// Defines the available drawing/editing tools

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
use vello::kurbo::Point;

/// Drawing and editing tools
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Tool {
    /// Selection tool - select and move objects
    Select,
    /// Draw/Pen tool - freehand drawing
    Draw,
    /// Transform tool - scale, rotate, skew
    Transform,
    /// Rectangle shape tool
    Rectangle,
    /// Ellipse/Circle shape tool
    Ellipse,
    /// Paint bucket - fill areas with color
    PaintBucket,
    /// Eyedropper - pick colors from the canvas
    Eyedropper,
    /// Line tool - draw straight lines
    Line,
    /// Polygon tool - draw polygons
    Polygon,
    /// Bezier edit tool - edit bezier curve control points
    BezierEdit,
    /// Text tool - add and edit text
    Text,
}

/// Tool state tracking for interactive operations
#[derive(Debug, Clone)]
pub enum ToolState {
    /// Tool is idle (no operation in progress)
    Idle,

    /// Drawing a freehand path
    DrawingPath {
        points: Vec<Point>,
        simplify_mode: SimplifyMode,
    },

    /// Dragging selected objects
    DraggingSelection {
        start_pos: Point,
        start_mouse: Point,
        original_positions: HashMap<Uuid, Point>,
    },

    /// Creating a marquee selection rectangle
    MarqueeSelecting {
        start: Point,
        current: Point,
    },

    /// Creating a rectangle shape
    CreatingRectangle {
        start_point: Point,      // Starting point (corner or center depending on modifiers)
        current_point: Point,    // Current mouse position
        centered: bool,          // If true, start_point is center; if false, it's a corner
        constrain_square: bool,  // If true, constrain to square (equal width/height)
    },

    /// Creating an ellipse shape
    CreatingEllipse {
        start_point: Point,      // Starting point (center or corner depending on modifiers)
        current_point: Point,    // Current mouse position
        corner_mode: bool,       // If true, start is corner; if false, start is center
        constrain_circle: bool,  // If true, constrain to circle (equal radii)
    },

    /// Transforming selected objects (scale, rotate)
    Transforming {
        mode: TransformMode,
        original_transforms: HashMap<Uuid, crate::object::Transform>,
        pivot: Point,
        start_mouse: Point,    // Mouse position when transform started
        current_mouse: Point,  // Current mouse position during drag
        original_bbox: vello::kurbo::Rect,  // Bounding box at start of transform (fixed)
    },

    /// Creating a line
    CreatingLine {
        start_point: Point,    // Starting point of the line
        current_point: Point,  // Current mouse position (end point)
    },

    /// Creating a polygon
    CreatingPolygon {
        center: Point,         // Center point of the polygon
        current_point: Point,  // Current mouse position (determines radius)
        num_sides: u32,        // Number of sides (from properties, default 5)
    },

    /// Editing a vertex (dragging it and connected curves)
    EditingVertex {
        shape_id: Uuid,                   // Which shape is being edited
        vertex_index: usize,              // Which vertex in the vertices array
        start_pos: Point,                 // Vertex position when drag started
        start_mouse: Point,               // Mouse position when drag started
        affected_curve_indices: Vec<usize>, // Which curves connect to this vertex
    },

    /// Editing a curve (reshaping with moldCurve algorithm)
    EditingCurve {
        shape_id: Uuid,            // Which shape is being edited
        curve_index: usize,        // Which curve in the curves array
        original_curve: vello::kurbo::CubicBez, // The curve when drag started
        start_mouse: Point,        // Mouse position when drag started
        parameter_t: f64,          // Parameter where the drag started (0.0-1.0)
    },

    /// Editing a control point (BezierEdit tool only)
    EditingControlPoint {
        shape_id: Uuid,            // Which shape is being edited
        curve_index: usize,        // Which curve owns this control point
        point_index: u8,           // 1 or 2 (p1 or p2 of the cubic bezier)
        original_curve: vello::kurbo::CubicBez, // The curve when drag started
        start_pos: Point,          // Control point position when drag started
    },
}

/// Path simplification mode for the draw tool
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SimplifyMode {
    /// Ramer-Douglas-Peucker corner detection
    Corners,
    /// Schneider curve fitting for smooth curves
    Smooth,
    /// No simplification (use raw points)
    Verbatim,
}

/// Transform mode for the transform tool
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TransformMode {
    /// Scale from a corner
    ScaleCorner { origin: Point },
    /// Scale along an edge
    ScaleEdge { axis: Axis, origin: Point },
    /// Rotate around a pivot
    Rotate { center: Point },
    /// Skew along an edge
    Skew { axis: Axis, origin: Point },
}

/// Axis for edge scaling
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Axis {
    Horizontal,
    Vertical,
}

impl Default for ToolState {
    fn default() -> Self {
        Self::Idle
    }
}

impl Tool {
    /// Get display name for the tool
    pub fn display_name(self) -> &'static str {
        match self {
            Tool::Select => "Select",
            Tool::Draw => "Draw",
            Tool::Transform => "Transform",
            Tool::Rectangle => "Rectangle",
            Tool::Ellipse => "Ellipse",
            Tool::PaintBucket => "Paint Bucket",
            Tool::Eyedropper => "Eyedropper",
            Tool::Line => "Line",
            Tool::Polygon => "Polygon",
            Tool::BezierEdit => "Bezier Edit",
            Tool::Text => "Text",
        }
    }

    /// Get SVG icon file name for the tool
    pub fn icon_file(self) -> &'static str {
        match self {
            Tool::Select => "select.svg",
            Tool::Draw => "draw.svg",
            Tool::Transform => "transform.svg",
            Tool::Rectangle => "rectangle.svg",
            Tool::Ellipse => "ellipse.svg",
            Tool::PaintBucket => "paint_bucket.svg",
            Tool::Eyedropper => "eyedropper.svg",
            Tool::Line => "line.svg",
            Tool::Polygon => "polygon.svg",
            Tool::BezierEdit => "bezier_edit.svg",
            Tool::Text => "text.svg",
        }
    }

    /// Get all available tools
    pub fn all() -> &'static [Tool] {
        &[
            Tool::Select,
            Tool::Draw,
            Tool::Transform,
            Tool::Rectangle,
            Tool::Ellipse,
            Tool::PaintBucket,
            Tool::Eyedropper,
            Tool::Line,
            Tool::Polygon,
            Tool::BezierEdit,
            Tool::Text,
        ]
    }

    /// Get keyboard shortcut hint
    pub fn shortcut_hint(self) -> &'static str {
        match self {
            Tool::Select => "V",
            Tool::Draw => "P",
            Tool::Transform => "Q",
            Tool::Rectangle => "R",
            Tool::Ellipse => "E",
            Tool::PaintBucket => "B",
            Tool::Eyedropper => "I",
            Tool::Line => "L",
            Tool::Polygon => "G",
            Tool::BezierEdit => "A",
            Tool::Text => "T",
        }
    }
}
