// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![allow(
    unsafe_code,
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::panic,
    missing_docs
)]

use jni::{
    descriptors::Desc,
    objects::{JObject, JString},
    sys::jint,
    JNIEnv, JavaVM,
};
use pourover::{
    desc::ClassDesc,
    exception::{null_pointer_exception, runtime_exception, JniResultExt, ThrowableJniResultExt},
};
use std::error::Error;

mod common;

use common::foo_class::*;

#[pourover::jni_method(package = "com.example", class = "Foo")]
extern "system" fn nativeReturnsInt<'local>(
    mut env: JNIEnv<'local>,
    _this: JObject<'local>,
    n: jint,
) -> jint {
    (|| match n {
        -1 => Err(runtime_exception("test runtime exception"))?,
        -2 => Err(null_pointer_exception())?,
        _ => Ok(n),
    })()
    .unwrap_or_throw(&mut env)
}

#[pourover::jni_method(
package = "com.example",
class = "Foo",
panic_returns = JObject::null().into(),
)]
extern "system" fn nativeReturnsObject<'local>(
    _env: JNIEnv<'local>,
    _this: JObject<'local>,
    _n: jint,
) -> JString<'local> {
    unimplemented!()
}

pub static RUNTIME_EXCEPTION_CLASS: ClassDesc = ClassDesc::new("java/lang/RuntimeException");

#[test]
fn can_call_native_method() -> Result<(), Box<dyn Error>> {
    // Create the environment
    let vm = JavaVM::new(
        jni::InitArgsBuilder::new()
            .version(jni::JNIVersion::V8)
            .option("-Xcheck:jni")
            .build()?,
    )?;
    let mut env = vm.attach_current_thread()?;

    // Load `Foo.class`
    {
        let foo_class = compile_foo()?;
        let loaded_foo = env.define_class(CLASS_DESC, &JObject::null(), &foo_class)?;
        env.delete_local_ref(loaded_foo)?;
    }

    let obj_foo = {
        let method_id = CONSTRUCTOR.lookup(&mut env)?;
        let args = &[jni::sys::jvalue { i: 123 }];
        // Safety: `args` must match the constructor arg count and types.
        unsafe { env.new_object_unchecked(CONSTRUCTOR.cls(), method_id, args) }?
    };
    let obj_foo = env.auto_local(obj_foo);

    // TODO: It would be better if the JVM was able to find the method on its own,
    // but, since we are using the invocation API to create the JVM, I haven't found a way to make
    // it visible to the JVM. Normally the methods are loaded dynamically with
    // `System.loadLibrary`, but in this case the symbols already exist in the executable, and I'm
    // unsure why the JVM cannot find them. I have tried compiling with
    // `-Zexport-executable-symbols` but that wasn't working for me.
    env.register_native_methods(
        &FOO,
        &[
            jni::NativeMethod {
                name: "nativeReturnsInt".into(),
                sig: "(I)I".into(),
                fn_ptr: crate::nativeReturnsInt as *mut std::ffi::c_void,
            },
            jni::NativeMethod {
                name: "nativeReturnsObject".into(),
                sig: "(I)Ljava/lang/String;".into(),
                fn_ptr: crate::nativeReturnsObject as *mut std::ffi::c_void,
            },
        ],
    )?;

    // Sub-test 1: Call nativeReturnsInt(99) returns the argument without exceptions
    {
        let result =
            pourover::call_method!(&mut env, FOO, "nativeReturnsInt", "(I)I", &obj_foo, 99);
        assert_eq!(99, result.unwrap());
    }

    // Sub-test 2: Call nativeReturnsInt(99) returns the argument without exceptions, so
    // extract_exception just returns Ok
    {
        let result =
            pourover::call_method!(&mut env, FOO, "nativeReturnsInt", "(I)I", &obj_foo, 99);
        let extracted_result = result.extract_exception(&mut env, "java/lang/Throwable");
        let Ok(Ok(99)) = extracted_result else {
            panic!("extracted_result should be Ok(Ok(99))")
        };
    }

    // Sub-test 3: Call nativeReturnsInt(-1) throws RuntimeException("test runtime exception")
    {
        let result =
            pourover::call_method!(&mut env, FOO, "nativeReturnsInt", "(I)I", &obj_foo, -1);
        let throwable = result
            .extract_exception(&mut env, "java/lang/RuntimeException")
            .unwrap()
            .unwrap_err();
        let message = pourover::call_method!(
            &mut env,
            RUNTIME_EXCEPTION_CLASS,
            "getMessage",
            "()Ljava/lang/String;",
            &throwable
        )
        .unwrap();
        let message = env.get_string(&message).map(String::from).unwrap();
        assert_eq!("test runtime exception", message);
    }

    // Sub-test 4: Call nativeReturnsInt(-2) throws NullPointerException()
    {
        let result =
            pourover::call_method!(&mut env, FOO, "nativeReturnsInt", "(I)I", &obj_foo, -2);
        let _ = result
            .extract_exception(&mut env, "java/lang/NullPointerException")
            .unwrap()
            .unwrap_err();
    }

    // Sub-test 5: Call nativeReturnsInt(-1) throws RuntimeException(). Calling
    // extract_exception with NullPointerException should return Err(JavaException).
    {
        let result =
            pourover::call_method!(&mut env, FOO, "nativeReturnsInt", "(I)I", &obj_foo, -1);

        let Err(jni::errors::Error::JavaException) =
            result.extract_exception(&mut env, "java/lang/NullPointerException")
        else {
            panic!(concat!(
                "Extracting NullPointerException from a result that contains RuntimeException ",
                "should return Err(JavaException)"
            ))
        };
        // The exception should still be pending on the JVM
        assert!(env.exception_check().unwrap());
    }

    Ok(())
}
