extern crate core;

use anyhow::Result;
use wasmtime::*;

// #[wasm_bindgen]
// extern {
//     pub fn alert(s: &str);
// }
//
// #[wasm_bindgen]
// pub fn greet(name: &str) {
//     alert(&format!("Hello, {}!", name));
// }
fn main() -> Result<()> {
    let engine = Engine::default();
    let wasm = std::fs::read("./examples/hello_wasm_bg.wasm")?;
    let module = Module::new(&engine, wasm)?;

    let mut linker = Linker::new(&engine);
    linker.func_wrap("./hello_wasm.js", "__wbg_alert_a5a2f68cc09adc6e", |caller: Caller<'_, u32>, param: i32, param2: i32| {
        let mut caller = caller;
        if let Extern::Memory(memory) = caller.get_export("memory").unwrap() {
            let mut buffer = vec![0; param2 as usize];
            memory.read(caller.as_context(), param as usize, &mut buffer).expect("read mem error");
            let s = String::from_utf8_lossy(&buffer).to_string();
            println!("[alert]: {}", s);
        } else {
            panic!("Should happen, got not memory");
        }
    })?;

    let mut store = Store::new(&engine, 0);
    let instance = linker.instantiate(&mut store, &module)?;

    let memory = instance.get_memory(&mut store, "memory")
        .ok_or_else(|| anyhow::format_err!("failed to find `memory` export"))?;
    // println!("memory size: {}", memory.size(&store));

    let msg = "hatter".as_bytes();
    let malloc_fn = instance.get_typed_func::<i32, i32>(&mut store, "__wbindgen_malloc")?;
    let msg_ptr = malloc_fn.call(&mut store, msg.len() as i32)?;
    memory.write(&mut store, msg_ptr as usize, msg)?;

    let greet_fn = instance.get_typed_func::<(i32, i32), ()>(&mut store, "greet")?;
    greet_fn.call(&mut store, (msg_ptr, msg.len() as i32))?;

    Ok(())
}

