// Copyright 2023 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.

//! Proc macros for `pourover`. These macros are reexported by the `pourover` crate, so this crate
//! is an implementation detail.

use proc_macro::TokenStream;

mod call_method;
mod jni_method;
mod type_parser;

/// Export a function as a JNI native method. This will attach a `#[export_name = "..."]` attribute that
/// is formatted with the given parameters. The provided `package`, `class`, and `method_name` will
/// be combined and formatted in according to the [JNI method name resolution rules][JNI naming].
///
/// [JNI naming]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names
///
/// # Parameters
/// - `package` (LitStr): the Java package for the class being implemented
/// - `class` (LitStr): the Java class being implemented. Use `Foo.Inner` syntax for inner
/// classes.
/// - `method_name` (*optional* LitStr): the method's name in Java. The Rust function name will be
/// used if this parameter is not set.
/// - `panic_returns` (*optional* Expr): the value to return when a panic is encountered. This can
/// not access local variables. This may only be used with `panic=unwind` and will produce a
/// compile error otherwise.
///
/// When using `panic_returns` function arguments must be [`std::panic::UnwindSafe`]. See
/// [`std::panic::catch_unwind`] for details. In practice this will not cause issues as JNI
/// arguments and return values are passed by pointer or value and not by Rust reference.
///
/// # Example
/// ```
/// # use pourover_macro::jni_method;
/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
///
/// #[jni_method(package = "my.package", class = "Foo", panic_returns = -1)]
/// extern "system" fn getFoo<'local>(
///     mut env: JNIEnv<'local>,
///     this: JObject<'local>,
/// ) -> jint {
///     // ...
///     0
/// }
/// ```
///
/// This function will be exported with `#[export_name = "Java_my_package_Foo_getFoo"]`.
#[proc_macro_attribute]
pub fn jni_method(meta: TokenStream, item: TokenStream) -> TokenStream {
    use quote::ToTokens;
    match jni_method::jni_method(meta.into(), item.into()) {
        Ok(item_fn) => item_fn.into_token_stream(),
        Err(err) => err.into_compile_error(),
    }
    .into()
}

/// Call a Java method.
///
/// # Parameters
/// `call_method!($env, $cls, $name, $sig, $this, $($args),*)`
/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
/// - `cls` (Expr: `&'static ClassDesc`): The class containing the method.
/// - `name` (Expr: `&'static str`): The name of the method.
/// - `sig` (LitStr): The JNI type signature of the method. This needs to be a literal so that it
/// can be parsed by the macro to type-check args and return a correctly-typed value.
/// - `this` (Expr: `&JObject`): The Java object receiving the method call.
/// - `args` (Expr ...): A variable number of arguments to be passed to the method.
///
/// # Caching
/// Each macro callsite will generate a `static` `MethodDesc` to cache the
/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
/// multiple times.
///
/// # Type-Safety
/// The given type signature will be parsed and arguments will be type checked against it. The
/// expected types are from the `jni` crate:
/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
///
/// Similarly, the return type will be one of the types above.
///
/// # Returns
/// The macro will evaluate to `jni::errors::Result<R>` where `R` is the return type parsed from
/// the type signature.
///
/// # Example
/// Let's call `sayHello` from the following class.
/// ```java
/// package com.example;
/// class Foo {
///     int sayHello(String name) { /* ... */ }
/// }
/// ```
/// We can use `call_method!` to implement the function call.
/// ```rust
/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
/// # use pourover_macro::call_method;
/// # use pourover::desc::*;
/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
/// fn say_hello<'l>(
///     env: &mut JNIEnv<'l>,
///     my_obj: &JObject<'_>,
///     name: &JString<'_>
/// ) -> jni::errors::Result<jint> {
///     call_method!(env, &MY_CLASS, "sayHello", "(Ljava/lang/String;)I", my_obj, name)
/// }
/// ```
#[proc_macro]
pub fn call_method(args: TokenStream) -> TokenStream {
    call_method::call_method(args.into())
        .unwrap_or_else(syn::Error::into_compile_error)
        .into()
}

/// Call a static Java method.
///
/// # Parameters
/// `call_static_method!($env, $cls, $name, $sig, $($args),*)`
/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
/// - `cls` (Expr: `&'static ClassDesc`): The class containing the method.
/// - `name` (Expr: `&'static str`): The name of the method.
/// - `sig` (LitStr): The JNI type signature of the method. This needs to be a literal so that it
/// can be parsed by the macro to type-check args and return a correctly-typed value.
/// - `args` (Expr ...): A variable number of arguments to be passed to the method.
///
/// # Caching
/// Each macro callsite will generate a `static` `StaticMethodDesc` to cache the
/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
/// multiple times.
///
/// # Type-Safety
/// The given type signature will be parsed and arguments will be type checked against it. The
/// expected types are from the `jni` crate:
/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
///
/// Similarly, the return type will be one of the types above.
///
/// # Returns
/// The macro will evaluate to `jni::errors::Result<R>` where `R` is the return type parsed from
/// the type signature.
///
/// # Example
/// Let's call `sayHello` from the following class.
/// ```java
/// package com.example;
/// class Foo {
///     static int sayHello(String name) { /* ... */ }
/// }
/// ```
/// We can use `call_static_method!` to implement the function call.
/// ```rust
/// # use jni::{sys::jint, objects::{JObject, JString}, JNIEnv};
/// # use pourover_macro::call_static_method;
/// # use pourover::desc::*;
/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
/// fn say_hello<'l>(
///     env: &mut JNIEnv<'l>,
///     name: &JString<'_>
/// ) -> jni::errors::Result<jint> {
///     call_static_method!(env, &MY_CLASS, "sayHello", "(Ljava/lang/String;)I", name)
/// }
/// ```
#[proc_macro]
pub fn call_static_method(args: TokenStream) -> TokenStream {
    call_method::call_static_method(args.into())
        .unwrap_or_else(syn::Error::into_compile_error)
        .into()
}

/// Call a Java constructor.
///
/// # Parameters
/// `call_constructor!($env, $cls, $sig, $($args),*)`
/// - `env` (Expr: `&mut jni::JNIEnv`): The JNI environment.
/// - `cls` (Expr: `&'static ClassDesc`): The class to be constructed.
/// - `sig` (LitStr): The JNI type signature of the constructor. This needs to be a literal so that it
/// can be parsed by the macro to type-check args and return a correctly-typed value.
/// - `args` (Expr ...): A variable number of arguments to be passed to the constructor.
///
/// # Caching
/// Each macro callsite will generate a `static` `MethodDesc` to cache the
/// method id. Due to this, **this macro call should be wrapped in function** instead of being called
/// multiple times.
///
/// # Type-Safety
/// The given type signature will be parsed and arguments will be type checked against it. The
/// expected types are from the `jni` crate:
/// - Primitives: `jni::sys::{jboolean, jbyte, jchar, jshort, jint, jlong, jfloat, jdouble}`
/// - Arrays: `jni::objects::{JPrimitiveArray, JObjectArray}`
/// - Objects: `jni::objects::{JObject, JString, JMap, JList}`
///
/// # Returns
/// The macro will evaluate to `jni::errors::Result<jni::objects::JObject>`.
///
/// # Example
/// Let's call the constructor from the following class.
/// ```java
/// package com.example;
/// class Foo {
///     Foo(String name) { /* ... */ }
/// }
/// ```
/// We can use `call_constructor!` to implement the function call.
/// ```rust
/// # use jni::{objects::{JObject, JString}, JNIEnv};
/// # use pourover_macro::call_constructor;
/// # use pourover::desc::*;
/// static MY_CLASS: ClassDesc = ClassDesc::new("com/example/Foo");
/// fn construct_foo<'l>(
///     env: &mut JNIEnv<'l>,
///     name: &JString<'_>
/// ) -> jni::errors::Result<JObject<'l>> {
///     call_constructor!(env, &MY_CLASS, "(Ljava/lang/String;)V", name)
/// }
/// ```
#[proc_macro]
pub fn call_constructor(args: TokenStream) -> TokenStream {
    call_method::call_constructor(args.into())
        .unwrap_or_else(syn::Error::into_compile_error)
        .into()
}

#[cfg(test)]
pub(crate) mod test_util {
    use proc_macro2::{TokenStream, TokenTree};

    /// Iterator that traverses TokenTree:Group structures in preorder.
    struct FlatStream {
        streams: Vec<<TokenStream as IntoIterator>::IntoIter>,
    }

    impl FlatStream {
        fn new(stream: TokenStream) -> Self {
            Self {
                streams: vec![stream.into_iter()],
            }
        }
    }

    impl Iterator for FlatStream {
        type Item = TokenTree;

        fn next(&mut self) -> Option<TokenTree> {
            let next = loop {
                let stream = self.streams.last_mut()?;
                if let Some(next) = stream.next() {
                    break next;
                }
                let _ = self.streams.pop();
            };

            if let TokenTree::Group(group) = &next {
                self.streams.push(group.stream().into_iter());
            }

            Some(next)
        }
    }

    pub fn contains_ident(stream: TokenStream, ident: &str) -> bool {
        FlatStream::new(stream)
            .filter_map(|tree| {
                let TokenTree::Ident(ident) = tree else {
                    return None;
                };
                Some(ident.to_string())
            })
            .any(|ident_str| ident_str == ident)
    }
}
