// src/frontend/props.rs

use glam::Mat4;
use glam::{Quat, Vec3};
use parking_lot::RwLock;
use std::sync::Arc;

pub type SharedProps = Arc<RwLock<DrawableProps>>;

/// Runtime visual state of a drawable.
/// This is authoritative for rendering and animation.
#[derive(Debug, Clone)]
pub struct DrawableProps {
    pub position: Vec3,
    pub rotation: Quat,
    pub scale: Vec3,
    pub visible: bool,
    pub opacity: f32,
    pub tag: Option<String>,
}

impl Default for DrawableProps {
    fn default() -> Self {
        Self {
            position: Vec3::ZERO,
            rotation: Quat::IDENTITY,
            scale: Vec3::ONE,
            visible: true,
            opacity: 1.0,
            tag: None,
        }
    }
}

/// Builder-style helpers
impl DrawableProps {
    pub fn identity() -> Self {
        Self {
            position: Vec3::ZERO,
            rotation: Quat::IDENTITY,
            scale: Vec3::ONE,
            visible: true,
            opacity: 1.0,
            tag: None,
        }
    }

    pub fn model_matrix(&self) -> Mat4 {
        Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.position)
    }

    pub fn at(mut self, pos: Vec3) -> Self {
        self.position = pos;
        self
    }

    pub fn scale_uniform(mut self, s: f32) -> Self {
        self.scale = Vec3::splat(s);
        self
    }

    pub fn scale(mut self, v: Vec3) -> Self {
        self.scale = v;
        self
    }

    pub fn rotate(mut self, q: Quat) -> Self {
        self.rotation = q;
        self
    }

    pub fn hide(mut self) -> Self {
        self.visible = false;
        self
    }

    pub fn show(mut self) -> Self {
        self.visible = true;
        self
    }

    pub fn opacity(mut self, v: f32) -> Self {
        self.opacity = v.clamp(0.0, 1.0);
        self
    }

    pub fn write(shared: &SharedProps) -> parking_lot::RwLockWriteGuard<'_, Self> {
        shared.write()
    }

    pub fn read(shared: &SharedProps) -> parking_lot::RwLockReadGuard<'_, Self> {
        shared.read()
    }
}
