use rlua::UserDataMethods;
use tealr::{TealData, TealDataMethods, TypeRepresentation, TypedFunction, UserData};
#[test]
fn generate_correct_type() {
    assert_eq!(
        TypedFunction::<String, String>::get_type_name(),
        "function(string):(string)"
    );
    assert_eq!(
        TypedFunction::<TypedFunction::<(i8, String), (String, u8)>, f32>::get_type_name(),
        "function(function(number,string):(string,number)):(number)"
    );
}
#[test]
fn try_to_use() -> rlua::Result<()> {
    #[derive(Clone, UserData, TypeRepresentation)]
    struct Test {}
    impl TealData for Test {
        fn add_methods<'lua, T: TealDataMethods<'lua, Self>>(methods: &mut T) {
            methods.add_method(
                "test_function_as_parameter",
                |_, _, x: TypedFunction<(u8, u8), u8>| x.call((10, 20)),
            );
        }
    }
    let code = tealr::compile_inline_teal!(
        "
global record Test 
    test_function_as_parameter:function(Test,function(number,number):number):number
end

global test: Test

function add(a:number,b:number):number
    return a + b
end
return test:test_function_as_parameter(add)
"
    );
    let res: u8 = rlua::Lua::new().context(|ctx| {
        let globals = ctx.globals();
        globals.set("test", Test {})?;
        ctx.load(code).eval()
    })?;
    assert_eq!(res, 30);
    Ok(())
}

#[test]
fn pass_back() -> rlua::Result<()> {
    #[derive(Clone, UserData, TypeRepresentation)]
    struct Test {}
    impl TealData for Test {
        fn add_methods<'lua, T: TealDataMethods<'lua, Self>>(methods: &mut T) {
            methods.add_method(
                "test_function_as_parameter",
                |_, _, x: TypedFunction<(u8, u8), u8>| Ok(x),
            );
        }
    }
    let code = tealr::compile_inline_teal!(
        "
global record Test 
    test_function_as_parameter:function(Test,function(number,number):number):(function(number,number):number)
end

global test: Test

function add(a:number,b:number):number
    return a + b
end
return test:test_function_as_parameter(add)(10,20)
"
    );
    let res: u8 = rlua::Lua::new().context(|ctx| {
        let globals = ctx.globals();
        globals.set("test", Test {})?;
        ctx.load(code).eval()
    })?;
    assert_eq!(res, 30);
    Ok(())
}
