use std::sync::Arc;
use crate::{
lua::{from_lua, get_metatable, into_lua, store_metatable},
shared::{func::call_function, object::pxs_PixelObject, pxs_Runtime, var::pxs_Var},
};
use anyhow::{Result, anyhow};
use mlua::prelude::*;
fn create_object_callback(lua: &Lua, fn_idx: i32, is_id: bool) -> Result<LuaFunction> {
let func = lua.create_function(
move |lua, (internal_obj, args): (LuaTable, LuaMultiValue)| -> Result<LuaValue, LuaError> {
let mut argv = vec![];
argv.push(pxs_Var::new_i64(pxs_Runtime::pxs_Lua as i64));
if is_id {
let obj_id: i64 = internal_obj
.get("_pxs_ptr")?;
argv.push(pxs_Var::new_i64(obj_id));
} else {
let obj_value = from_lua(internal_obj.to_value());
if obj_value.is_err() {
return Err(LuaError::RuntimeError(obj_value.unwrap_err().to_string()));
}
argv.push(
obj_value.unwrap()
);
}
for arg in args {
let lua_arg = from_lua(arg);
if lua_arg.is_err() {
return Err(LuaError::RuntimeError(lua_arg.unwrap_err().to_string()));
}
argv.push(lua_arg.unwrap());
}
unsafe {
let res = call_function(fn_idx, argv);
let lua_val = into_lua(lua, &res);
lua_val
}
},
);
if func.is_err() {
Err(anyhow!("{:#}", func.unwrap_err()))
} else {
Ok(func.unwrap())
}
}
pub(super) fn create_object(lua: &Lua, idx: i32, source: Arc<pxs_PixelObject>) -> Result<LuaTable> {
let table = lua.create_table()?;
table.set("_pxs_ptr", LuaValue::Integer(idx as i64))?;
let metatable = get_metatable(&source.type_name);
let metatable = if let Some(mt) = metatable {
mt.clone()
} else {
let mt = lua.create_table()?;
for method in source.callbacks.iter() {
let func = create_object_callback(lua, method.cbk.idx, method.is_id)?;
mt.set(method.cbk.name.clone(), func)?;
}
mt.set("__index", mt.clone())?;
store_metatable(&source.type_name, mt.clone());
mt
};
table.set_metatable(Some(metatable))?;
Ok(table)
}