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

use crate::lua::LuaEnv;

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl Color {
    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
        Color { r, g, b, a }
    }

    pub fn to_rgba(&self) -> Rgba<u8> {
        Rgba([self.r, self.g, self.b, self.a])
    }
}

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

impl UserData for Color {
    fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
        methods.add_method_mut("set_r", |_, color, x: u8| {
            color.r = x;
            Ok(())
        });
        methods.add_method_mut("set_g", |_, color, x: u8| {
            color.g = x;
            Ok(())
        });
        methods.add_method_mut("set_b", |_, color, x: u8| {
            color.b = x;
            Ok(())
        });
        methods.add_method_mut("set_a", |_, color, x: u8| {
            color.a = x;
            Ok(())
        });

        methods.add_method("get_r", |_, color, ()| Ok(color.r));
        methods.add_method("get_g", |_, color, ()| Ok(color.g));
        methods.add_method("get_b", |_, color, ()| Ok(color.b));
        methods.add_method("get_a", |_, color, ()| Ok(color.a));
    }
}

pub fn add_constructor(lua: &LuaEnv) -> crate::Result<()> {
    lua.func("Color", |_, (r, g, b)| Ok(Color::new(r, g, b, 255)))?;
    lua.func("ColorRGB", |_, (r, g, b)| Ok(Color::new(r, g, b, 255)))?;
    lua.func("ColorRGBA", |_, (r, g, b, a)| Ok(Color::new(r, g, b, a)))?;
    Ok(())
}
