use mlua::{FromLua, Lua, UserData, UserDataMethods};

use crate::lua::LuaEnv;
pub use crate::renderer::prelude::*;

#[derive(Debug, Clone, PartialEq, Copy)]
pub struct RectangleElement {
    pub position: Point,
    pub size: Size,
    pub color: Color,
    pub filled: bool,
    pub border_thickness: f64,
}

impl RectangleElement {
    pub fn new(
        position: Point,
        size: Size,
        color: Color,
        filled: bool,
        border_thickness: f64,
    ) -> Self {
        RectangleElement {
            position,
            size,
            color,
            filled,
            border_thickness,
        }
    }
}

impl FromLua for RectangleElement {
    fn from_lua(value: mlua::Value, _: &Lua) -> mlua::Result<Self> {
        match value {
            mlua::Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
            _ => unreachable!(),
        }
    }
}

impl UserData for RectangleElement {
    fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
        methods.add_method_mut("set_point", |_, rect, point: Point| {
            rect.position = point;
            Ok(())
        });
        methods.add_method_mut("set_size", |_, rect, size: Size| {
            rect.size = size;
            Ok(())
        });
        methods.add_method_mut("set_color", |_, rect, color: Color| {
            rect.color = color;
            Ok(())
        });
        methods.add_method_mut("set_thickness", |_, rect, thickness: f64| {
            rect.border_thickness = thickness;
            Ok(())
        });
        methods.add_method_mut("set_filled", |_, rect, filled: bool| {
            rect.filled = filled;
            Ok(())
        });

        methods.add_method("get_point", |_, rect, ()| Ok(rect.position));
        methods.add_method("get_color", |_, rect, ()| Ok(rect.color));
        methods.add_method("get_thickness", |_, rect, ()| Ok(rect.border_thickness));
        methods.add_method("get_filled", |_, rect, ()| Ok(rect.filled));
    }
}

pub fn add_constructor(lua: &LuaEnv) -> crate::Result<()> {
    lua.func("Rect", |_, (position, size, color)| {
        Ok(Element::Rectangle(RectangleElement::new(
            position, size, color, true, 0.,
        )))
    })?;
    lua.func("RectOutline", |_, (position, size, color, thickness)| {
        Ok(Element::Rectangle(RectangleElement::new(
            position, size, color, false, thickness,
        )))
    })?;
    Ok(())
}
