//! Generic Icon System for egui
//!
//! Provides a generic SVG-based icon system with:
//! - Compile-time SVG tessellation via build script
//! - Runtime rendering with dynamic colors and sizes
//! - Zero runtime SVG parsing overhead
//!
//! # Architecture
//!
//! This crate provides the core infrastructure for icons:
//! - [`IconData`] - Pre-tessellated icon geometry
//! - [`render_icon`] - Renders icon data to an egui painter
//! - [`Icon`] - Generic icon widget
//!
//! Specific icon sets (transport controls, window controls, etc.) should be
//! defined in their own crates using the build script utilities from this crate.
//!
//! # Example
//!
//! ```rust,no_run
//! use armas_icon::{Icon, IconData};
//! use egui::{Color32, Ui};
//!
//! // Define your icon data (typically generated by build script)
//! static MY_ICON: IconData = IconData {
//!     name: "my_icon",
//!     vertices: &[(0.0, 0.0), (24.0, 12.0), (0.0, 24.0)],
//!     indices: &[0, 1, 2],
//!     viewbox_width: 24.0,
//!     viewbox_height: 24.0,
//! };
//!
//! fn show_icon(ui: &mut Ui) {
//!     Icon::new(&MY_ICON)
//!         .size(24.0)
//!         .color(Color32::WHITE)
//!         .show(ui);
//! }
//! ```

#[cfg(feature = "build")]
pub mod build;

use egui::{epaint::Vertex, Color32, Mesh, Painter, Pos2, Rect, Response, Sense, Ui, Vec2};

/// Pre-tessellated icon data
///
/// Contains the geometry data for rendering an icon. This is typically
/// generated at compile time from SVG files using the build script.
#[derive(Debug, Clone)]
pub struct IconData {
    /// Icon name (for debugging)
    pub name: &'static str,
    /// Vertex positions as (x, y) tuples
    pub vertices: &'static [(f32, f32)],
    /// Triangle indices
    pub indices: &'static [u32],
    /// Original viewbox width
    pub viewbox_width: f32,
    /// Original viewbox height
    pub viewbox_height: f32,
}

/// Render icon data to an egui painter
///
/// Transforms and renders the pre-tessellated icon geometry to fit
/// within the given rectangle, maintaining aspect ratio and centering.
pub fn render_icon(painter: &Painter, rect: Rect, icon_data: &IconData, color: Color32) {
    let scale_x = rect.width() / icon_data.viewbox_width;
    let scale_y = rect.height() / icon_data.viewbox_height;
    let scale = scale_x.min(scale_y);

    let offset_x = rect.left() + icon_data.viewbox_width.mul_add(-scale, rect.width()) / 2.0;
    let offset_y = rect.top() + icon_data.viewbox_height.mul_add(-scale, rect.height()) / 2.0;

    let mut mesh = Mesh::default();

    // Transform vertices and add to mesh
    for (x, y) in icon_data.vertices {
        let pos = Pos2::new(offset_x + x * scale, offset_y + y * scale);
        mesh.vertices.push(Vertex {
            pos,
            uv: Pos2::ZERO,
            color,
        });
    }

    // Add indices
    mesh.indices.extend_from_slice(icon_data.indices);

    painter.add(mesh);
}

/// Generic icon widget
///
/// Renders any [`IconData`] with configurable size and color.
///
/// # Example
///
/// ```rust,no_run
/// # use armas_icon::{Icon, IconData};
/// # use egui::{Color32, Ui};
/// # static MY_ICON: IconData = IconData {
/// #     name: "test", vertices: &[], indices: &[],
/// #     viewbox_width: 24.0, viewbox_height: 24.0,
/// # };
/// # fn example(ui: &mut Ui) {
/// Icon::new(&MY_ICON)
///     .size(32.0)
///     .color(Color32::RED)
///     .show(ui);
/// # }
/// ```
pub struct Icon<'a> {
    icon_data: &'a IconData,
    size: f32,
    color: Color32,
}

impl<'a> Icon<'a> {
    /// Create a new icon widget
    #[must_use]
    pub const fn new(icon_data: &'a IconData) -> Self {
        Self {
            icon_data,
            size: 24.0,
            color: Color32::WHITE,
        }
    }

    /// Set the icon size (width and height will be equal)
    #[must_use]
    pub const fn size(mut self, size: f32) -> Self {
        self.size = size;
        self
    }

    /// Set the icon color
    #[must_use]
    pub const fn color(mut self, color: Color32) -> Self {
        self.color = color;
        self
    }

    /// Show the icon
    pub fn show(self, ui: &mut Ui) -> Response {
        let (rect, response) = ui.allocate_exact_size(Vec2::splat(self.size), Sense::click());

        if ui.is_rect_visible(rect) {
            if self.icon_data.vertices.is_empty() {
                // Fallback: draw a placeholder if icon data is empty
                ui.painter().rect_filled(rect, 2.0, Color32::from_gray(100));
            } else {
                render_icon(ui.painter(), rect, self.icon_data, self.color);
            }
        }

        response
    }
}
