use std::any::Any;
use crate::core::Component;
use crate::math::Vec2;

#[derive(Debug, Clone, PartialEq)]
pub struct Sprite {
    pub texture_path: String,  // 텍스처 파일 경로
    pub visible: bool,         // 가시성
    pub size: Vec2,           // 스프라이트 크기 (픽셀 단위)
    pub color: Color,         // 색상 틴트
    pub flip_x: bool,         // X축 뒤집기
    pub flip_y: bool,         // Y축 뒤집기
    pub layer: i32,           // 렌더링 레이어 (낮을수록 뒤쪽)
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Color {
    pub r: f32,  // 빨강 (0.0 ~ 1.0)
    pub g: f32,  // 초록 (0.0 ~ 1.0)
    pub b: f32,  // 파랑 (0.0 ~ 1.0)
    pub a: f32,  // 투명도 (0.0 ~ 1.0)
}

impl Color {
    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
        assert!((0.0..=1.0).contains(&r), "Red component must be in range 0.0-1.0, got: {}", r);
        assert!((0.0..=1.0).contains(&g), "Green component must be in range 0.0-1.0, got: {}", g);
        assert!((0.0..=1.0).contains(&b), "Blue component must be in range 0.0-1.0, got: {}", b);
        assert!((0.0..=1.0).contains(&a), "Alpha component must be in range 0.0-1.0, got: {}", a);
        
        Self { r, g, b, a }
    }
    
    /// RGB 값으로 생성 (알파는 1.0)
    pub fn rgb(r: f32, g: f32, b: f32) -> Self {
        Self::new(r, g, b, 1.0)
    }
    
    pub fn white() -> Self {
        Self::new(1.0, 1.0, 1.0, 1.0)
    }
    
    pub fn black() -> Self {
        Self::new(0.0, 0.0, 0.0, 1.0)
    }
    
    pub fn red() -> Self {
        Self::new(1.0, 0.0, 0.0, 1.0)
    }
    
    pub fn green() -> Self {
        Self::new(0.0, 1.0, 0.0, 1.0)
    }
    
    pub fn blue() -> Self {
        Self::new(0.0, 0.0, 1.0, 1.0)
    }
    
    pub fn transparent() -> Self {
        Self::new(1.0, 1.0, 1.0, 0.0)
    }
    
    /// 색상 혼합 (t: 0.0~1.0, 0.0=첫번째 색상, 1.0=두번째 색상)
    pub fn lerp(&self, other: Color, t: f32) -> Self {
        assert!((0.0..=1.0).contains(&t), "Interpolation factor must be in range 0.0-1.0, got: {}", t);
        Self::new(
            self.r + (other.r - self.r) * t,
            self.g + (other.g - self.g) * t,
            self.b + (other.b - self.b) * t,
            self.a + (other.a - self.a) * t,
        )
    }
    
    /// 투명도 설정
    pub fn with_alpha(&self, alpha: f32) -> Self {
        assert!((0.0..=1.0).contains(&alpha), "Alpha must be in range 0.0-1.0, got: {}", alpha);
        Self::new(self.r, self.g, self.b, alpha)
    }
}

impl Sprite {
    pub fn new(texture_path: &str) -> Self {
        Self {
            texture_path: texture_path.to_string(),
            visible: true,
            size: Vec2::new(32.0, 32.0), // 기본 32x32 픽셀
            color: Color::white(),
            flip_x: false,
            flip_y: false,
            layer: 0,
        }
    }
    
    pub fn default() -> Self {
        Self::new("")
    }
    
    /// 텍스처 경로와 크기로 생성
    pub fn with_size(texture_path: &str, width: f32, height: f32) -> Self {
        Self {
            texture_path: texture_path.to_string(),
            visible: true,
            size: Vec2::new(width, height),
            color: Color::white(),
            flip_x: false,
            flip_y: false,
            layer: 0,
        }
    }
    
    /// 가시성 설정
    pub fn set_visible(&mut self, visible: bool) {
        self.visible = visible;
    }
    
    /// 가시성 토글
    pub fn toggle_visible(&mut self) {
        self.visible = !self.visible;
    }
    
    /// 크기 설정
    pub fn set_size(&mut self, width: f32, height: f32) {
        self.size = Vec2::new(width, height);
    }
    
    /// 균등 크기 설정
    pub fn set_uniform_size(&mut self, size: f32) {
        self.size = Vec2::new(size, size);
    }
    
    /// 색상 설정
    pub fn set_color(&mut self, color: Color) {
        self.color = color;
    }
    
    /// 색상을 RGB로 설정 (0.0 ~ 1.0)
    pub fn set_color_rgb(&mut self, r: f32, g: f32, b: f32) {
        self.color = Color::rgb(r, g, b);
    }
    
    /// 투명도 설정
    pub fn set_alpha(&mut self, alpha: f32) {
        assert!((0.0..=1.0).contains(&alpha), "Alpha must be in range 0.0-1.0, got: {}", alpha);
        self.color.a = alpha;
    }
    
    pub fn set_flip_x(&mut self, flip: bool) {
        self.flip_x = flip;
    }
    
    pub fn set_flip_y(&mut self, flip: bool) {
        self.flip_y = flip;
    }
    
    /// 렌더링 레이어 설정
    pub fn set_layer(&mut self, layer: i32) {
        self.layer = layer;
    }
    
    /// 텍스처 경로 설정
    pub fn set_texture(&mut self, texture_path: &str) {
        self.texture_path = texture_path.to_string();
    }
    
    /// 가시성 확인
    pub fn is_visible(&self) -> bool {
        self.visible && self.color.a > 0.0
    }
    
    /// 텍스처가 설정되어 있는지 확인
    pub fn has_texture(&self) -> bool {
        !self.texture_path.is_empty()
    }
}

impl Component for Sprite {
    fn as_any(&self) -> &dyn Any {
        self
    }
    
    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
    
    fn clone_box(&self) -> Box<dyn Component> {
        Box::new(self.clone())
    }
}