use mlua::IntoLua;

#[derive(Clone,Copy)]
pub struct Enum(u32);
#[derive(Clone,Copy)]
pub struct EnumItems;
#[derive(Clone,Copy)]
pub struct EnumItem<'a>{
	ed:&'a rbx_reflection::EnumDescriptor<'a>,
}

impl Into<rbx_types::Enum> for Enum{
	fn into(self)->rbx_types::Enum{
		rbx_types::Enum::from_u32(self.0)
	}
}

impl<'a> EnumItem<'a>{
	const fn new(ed:&'a rbx_reflection::EnumDescriptor)->Self{
		Self{ed}
	}
}

pub fn set_globals(_lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
	globals.set("Enum",EnumItems)
}

impl mlua::UserData for EnumItem<'_>{
	fn add_fields<F:mlua::UserDataFields<Self>>(_fields:&mut F){
	}
	fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
		methods.add_meta_function(mlua::MetaMethod::Index,|lua,(this,val):(EnumItem<'_>,mlua::String)|{
			match this.ed.items.get(&*val.to_str()?){
				Some(&id)=>Enum(id).into_lua(lua),
				None=>mlua::Value::Nil.into_lua(lua),
			}
		});
	}
}
type_from_lua_userdata_lua_lifetime!(EnumItem);

impl mlua::UserData for EnumItems{
	fn add_fields<F:mlua::UserDataFields<Self>>(_fields:&mut F){
	}
	fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
		methods.add_meta_function(mlua::MetaMethod::Index,|lua,(_,val):(Self,mlua::String)|{
			let db=rbx_reflection_database::get();
			match db.enums.get(&*val.to_str()?){
				Some(ed)=>EnumItem::new(ed).into_lua(lua),
				None=>mlua::Value::Nil.into_lua(lua),
			}
		});
	}
}
type_from_lua_userdata!(EnumItems);

impl mlua::UserData for Enum{
	fn add_fields<F:mlua::UserDataFields<Self>>(_fields:&mut F){
	}
	fn add_methods<M:mlua::UserDataMethods<Self>>(_methods:&mut M){
	}
}
type_from_lua_userdata!(Enum);
