use super::text_properties::{TextAlignment, TextProperties, VerticalAlignment};
use nalgebra_glm::{Vec2, Vec3, Vec4};

#[derive(Clone, Debug)]
pub struct TextMesh {
    pub vertices: Vec<TextVertex>,
    pub indices: Vec<u32>,
    pub bounds: Vec2,
}

#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct TextVertex {
    pub position: Vec3,
    pub tex_coords: Vec2,
}

#[derive(Clone, Debug)]
pub struct Text {
    pub text_index: usize,
    pub properties: TextProperties,
    pub font_index: usize,
    pub dirty: bool,
    pub cached_mesh: Option<TextMesh>,
    pub billboard: bool,
}

impl Default for Text {
    fn default() -> Self {
        Self {
            text_index: 0,
            properties: TextProperties::default(),
            font_index: 0,
            dirty: true,
            cached_mesh: None,
            billboard: false,
        }
    }
}

impl Text {
    pub fn new(text_index: usize) -> Self {
        Self {
            text_index,
            properties: TextProperties::default(),
            font_index: 0,
            dirty: true,
            cached_mesh: None,
            billboard: false,
        }
    }

    pub fn with_billboard(mut self, billboard: bool) -> Self {
        self.billboard = billboard;
        self
    }

    pub fn set_billboard(&mut self, billboard: bool) {
        self.billboard = billboard;
    }

    pub fn with_properties(mut self, properties: TextProperties) -> Self {
        self.properties = properties;
        self.dirty = true;
        self
    }

    pub fn with_font(mut self, font_index: usize) -> Self {
        self.font_index = font_index;
        self.dirty = true;
        self
    }

    pub fn set_text_index(&mut self, text_index: usize) {
        self.text_index = text_index;
        self.dirty = true;
    }

    pub fn set_color(&mut self, color: Vec4) {
        self.properties.color = color;
        self.dirty = true;
    }

    pub fn set_font_size(&mut self, size: f32) {
        self.properties.font_size = size;
        self.dirty = true;
    }

    pub fn set_alignment(&mut self, alignment: TextAlignment) {
        self.properties.alignment = alignment;
        self.dirty = true;
    }

    pub fn set_vertical_alignment(&mut self, alignment: VerticalAlignment) {
        self.properties.vertical_alignment = alignment;
        self.dirty = true;
    }

    pub fn set_line_height(&mut self, line_height: f32) {
        self.properties.line_height = line_height;
        self.dirty = true;
    }

    pub fn set_letter_spacing(&mut self, spacing: f32) {
        self.properties.letter_spacing = spacing;
        self.dirty = true;
    }

    pub fn set_outline(&mut self, width: f32, color: Vec4) {
        self.properties.outline_width = width;
        self.properties.outline_color = color;
        self.dirty = true;
    }

    pub fn set_smoothing(&mut self, smoothing: f32) {
        self.properties.smoothing = smoothing;
        self.dirty = true;
    }

    pub fn set_properties(&mut self, properties: TextProperties) {
        self.properties = properties;
        self.dirty = true;
    }

    pub fn set_font_index(&mut self, font_index: usize) {
        self.font_index = font_index;
        self.dirty = true;
    }

    pub fn get_bounds(&self) -> Option<Vec2> {
        self.cached_mesh.as_ref().map(|mesh| mesh.bounds)
    }
}
