use alloc::string::String;
use core::ffi::CStr;
use luaur_common::functions::starts_with::startsWith;
use luaur_vm::enums::lua_type::lua_Type;
use luaur_vm::functions::lua_next::lua_next;
use luaur_vm::functions::lua_pushnil::lua_pushnil;
use luaur_vm::functions::lua_type::lua_type;
use luaur_vm::macros::lua_istable::lua_istable;
use luaur_vm::macros::lua_pop::lua_pop;
use luaur_vm::macros::lua_tostring::lua_tostring;
use luaur_vm::type_aliases::lua_state::lua_State;
use crate::functions::try_replace_top_with_index::try_replace_top_with_index;
const MAX_TRAVERSAL_LIMIT: i32 = 50;
pub unsafe fn complete_partial_matches(
l: *mut lua_State,
complete_only_functions: bool,
edit_buffer: &str,
prefix: &str,
add_completion_callback: &dyn Fn(&str, &str),
) {
let mut i = 0;
while i < MAX_TRAVERSAL_LIMIT && lua_istable!(l, -1) {
lua_pushnil(l);
while lua_next(l, -2) != 0 {
if lua_type(l, -2) == lua_Type::LUA_TSTRING as i32 {
let key_ptr = lua_tostring!(l, -2);
let key = CStr::from_ptr(key_ptr).to_string_lossy();
let value_type = lua_type(l, -1);
let required_value_type =
!complete_only_functions || value_type == lua_Type::LUA_TFUNCTION as i32;
if !key.is_empty() && required_value_type && startsWith(&key, prefix) {
let completed_component = &key[prefix.len()..];
let mut completion =
String::with_capacity(edit_buffer.len() + completed_component.len() + 1);
completion.push_str(edit_buffer);
completion.push_str(completed_component);
if value_type == lua_Type::LUA_TFUNCTION as i32 {
completion.push('(');
}
add_completion_callback(&completion, &key);
}
}
lua_pop(l, 1);
}
if !try_replace_top_with_index(l) {
break;
}
i += 1;
}
}