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

//! Cacheable descriptors. These `jni` crate compatible descriptors will cache their value on first
//! lookup. They are meant to be combined with static variables in order to globally cache their
//! associated id values.
//!
//! ### Example
//!
//! ```java
//! package com.example;
//!
//! public class MyClass {
//!     public int foo;
//!     public int getBar() { /* ... */ }
//! }
//! ```
//!
//! ```rust
//! use pourover::desc::*;
//!
//! static MY_CLASS_DESC: ClassDesc = ClassDesc::new("com/example/MyClass");
//! static MY_CLASS_FOO_FIELD: FieldDesc = MY_CLASS_DESC.field("foo", "I");
//! static MY_CLASS_GET_BAR_METHOD: MethodDesc = MY_CLASS_DESC.method("getBar", "I()");
//! ```

#![allow(unsafe_code)]

use jni::{
    descriptors::Desc,
    objects::{GlobalRef, JClass, JFieldID, JMethodID, JObject, JStaticFieldID, JStaticMethodID},
    JNIEnv,
};
use std::sync::{LockResult, RwLock, RwLockReadGuard};

/// JNI descriptor that caches a Java class.
pub struct ClassDesc {
    /// The JNI descriptor for this class.
    descriptor: &'static str,
    /// The cached class
    ///
    /// The implementation assumes that `None` is only written to the lock when `&mut self` is
    /// held. Only `Some` is valid to write to this lock while `&self` is held.
    cls: RwLock<Option<GlobalRef>>,
}

impl ClassDesc {
    /// Create a new descriptor with the given JNI descriptor string.
    pub const fn new(descriptor: &'static str) -> Self {
        Self {
            descriptor,
            cls: RwLock::new(None),
        }
    }

    /// Create a new descriptor for a field member of this class.
    pub const fn field<'cls>(&'cls self, name: &'static str, sig: &'static str) -> FieldDesc<'cls> {
        FieldDesc::new(self, name, sig)
    }

    /// Create a new descriptor for a static field member of this class.
    pub const fn static_field<'cls>(
        &'cls self,
        name: &'static str,
        sig: &'static str,
    ) -> StaticFieldDesc<'cls> {
        StaticFieldDesc::new(self, name, sig)
    }

    /// Create a new descriptor for a method member of this class.
    pub const fn method<'cls>(
        &'cls self,
        name: &'static str,
        sig: &'static str,
    ) -> MethodDesc<'cls> {
        MethodDesc::new(self, name, sig)
    }

    /// Create a new descriptor for a constructor for this class.
    pub const fn constructor<'cls>(&'cls self, sig: &'static str) -> MethodDesc<'cls> {
        MethodDesc::new(self, "<init>", sig)
    }

    /// Create a new descriptor for a static method member of this class.
    pub const fn static_method<'cls>(
        &'cls self,
        name: &'static str,
        sig: &'static str,
    ) -> StaticMethodDesc<'cls> {
        StaticMethodDesc::new(self, name, sig)
    }

    /// Free the cached GlobalRef to the class object. This will happen automatically on drop, but
    /// this method is provided to allow the value to be dropped early. This can be used to perform
    /// cleanup on a thread that is already attached to the JVM.
    pub fn free(&mut self) {
        // Get a mutable reference ignoring poison state
        let mut guard = self.cls.write().ignore_poison();
        let global = guard.take();
        // Drop the guard before global in case it panics. We don't want to poison the lock.
        core::mem::drop(guard);
        // Drop the GlobalRef value to cleanup
        core::mem::drop(global);
    }

    fn get_cached(&self) -> Option<CachedClass<'_>> {
        CachedClass::from_lock(&self.cls)
    }
}

/// Wrapper to allow RwLock references to be returned from Desc. Use the `AsRef` impl to get the
/// associated `JClass` reference. The inner `Option` must always be `Some`. This is enfocred by
/// the `from_lock` constructor.
pub struct CachedClass<'lock>(RwLockReadGuard<'lock, Option<GlobalRef>>);

impl<'lock> CachedClass<'lock> {
    /// Read from the given lock and create a `CachedClass` instance if the lock contains a cached
    /// class value. The given lock must have valid data even if it is poisoned.
    fn from_lock(lock: &'lock RwLock<Option<GlobalRef>>) -> Option<CachedClass<'lock>> {
        let guard = lock.read().ignore_poison();

        // Validate that there is a GlobalRef value already, otherwise avoid constructing `Self`.
        if guard.is_some() {
            Some(Self(guard))
        } else {
            None
        }
    }
}

// Implement AsRef so that we can use this type as `Desc::Output` in [`ClassDesc`].
impl AsRef<JClass<'static>> for CachedClass<'_> {
    fn as_ref(&self) -> &JClass<'static> {
        // `unwrap` is valid since we checked for `Some` in the constructor.
        #[allow(clippy::expect_used)]
        let global = self
            .0
            .as_ref()
            .expect("Created CachedClass in an invalid state");
        // No direct conversion to JClass, so let's go through JObject first.
        let obj: &JObject<'static> = global.as_ref();
        // This assumes our object is a class object.
        let cls: &JClass<'static> = From::from(obj);
        cls
    }
}

/// # Safety
///
/// This returns the correct class instance via `JNIEnv::find_class`. The cached class is held in a
/// [`GlobalRef`] so that it cannot be unloaded.
unsafe impl<'a, 'local> Desc<'local, JClass<'static>> for &'a ClassDesc {
    type Output = CachedClass<'a>;

    fn lookup(self, env: &mut JNIEnv<'local>) -> jni::errors::Result<Self::Output> {
        // Check the cache
        if let Some(cls) = self.get_cached() {
            return Ok(cls);
        }

        {
            // Ignoring poison is fine because we only write fully-constructed values.
            let mut guard = self.cls.write().ignore_poison();

            // Multiple threads could have hit this block at the same time. Only allocate the
            // `GlobalRef` if it was not already allocated.
            if guard.is_none() {
                let cls = env.find_class(self.descriptor)?;
                let global = env.new_global_ref(cls)?;

                // Only directly assign valid values. That way poison state can't have broken
                // invariants. If the above panicked then it will poison without changing the
                // lock's data, and everything will still be fine albeit with a sprinkle of
                // possibly-leaked memory.
                *guard = Some(global);
            }
        }

        // Safe to unwrap since we just set `self.cls` to `Some`. `ClassDesc::free` can't be called
        // before this point because it takes a mutable reference to `*self`.
        #[allow(clippy::unwrap_used)]
        Ok(self.get_cached().unwrap())
    }
}

/// A descriptor for a class member. `Id` is expected to implement the [`MemberId`] trait.
///
/// See [`FieldDesc`], [`StaticFieldDesc`], [`MethodDesc`], and [`StaticMethodDesc`] aliases.
pub struct MemberDesc<'cls, Id> {
    cls: &'cls ClassDesc,
    name: &'static str,
    sig: &'static str,
    id: RwLock<Option<Id>>,
}

/// Descriptor for a field.
pub type FieldDesc<'cls> = MemberDesc<'cls, JFieldID>;
/// Descriptor for a static field.
pub type StaticFieldDesc<'cls> = MemberDesc<'cls, JStaticFieldID>;
/// Descriptor for a method.
pub type MethodDesc<'cls> = MemberDesc<'cls, JMethodID>;
/// Descriptor for a static method.
pub type StaticMethodDesc<'cls> = MemberDesc<'cls, JStaticMethodID>;

impl<'cls, Id: MemberId> MemberDesc<'cls, Id> {
    /// Create a new descriptor for a member of the given class with the given name and signature.
    ///
    /// Please use the helpers on [`ClassDesc`] instead of directly calling this method.
    pub const fn new(cls: &'cls ClassDesc, name: &'static str, sig: &'static str) -> Self {
        Self {
            cls,
            name,
            sig,
            id: RwLock::new(None),
        }
    }

    /// Get the class descriptor that this member is associated to.
    pub const fn cls(&self) -> &'cls ClassDesc {
        self.cls
    }
}

/// # Safety
///
/// This returns the correct id. It is the same id obtained from the JNI. This id can be a pointer
/// in some JVM implementations. See trait [`MemberId`].
unsafe impl<'local, Id: MemberId> Desc<'local, Id> for &MemberDesc<'_, Id> {
    type Output = Id;

    fn lookup(self, env: &mut JNIEnv<'local>) -> jni::errors::Result<Self::Output> {
        // Check the cache.
        if let Some(id) = *self.id.read().ignore_poison() {
            return Ok(id);
        }

        {
            // Ignoring poison is fine because we only write valid values.
            let mut guard = self.id.write().ignore_poison();

            // Multiple threads could have hit this block at the same time. Only lookup the id if
            // the lookup was not already performed.
            if guard.is_none() {
                let id = Id::lookup(env, self)?;

                // Only directly assign valid values. That way poison state can't have broken
                // invariants. If the above panicked then it will poison without changing the
                // lock's data and everything will still be fine.
                *guard = Some(id);

                Ok(id)
            } else {
                // Can unwrap since we just checked for `None`.
                #[allow(clippy::unwrap_used)]
                Ok(*guard.as_ref().unwrap())
            }
        }
    }
}

/// Helper trait that calls into `jni` to lookup the id values. This is specialized on the id's
/// type to call the correct lookup function.
///
/// # Safety
///
/// Implementers must be an ID returned from the JNI. `lookup` must be implemented such that the
/// returned ID matches the JNI descriptor given. All values must be sourced from the JNI APIs.
/// See [`::jni::descriptors::Desc`].
pub unsafe trait MemberId: Sized + Copy + AsRef<Self> {
    /// Lookup the id of the given descriptor via the given environment.
    fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self>;
}

/// # Safety
///
/// This fetches the matching ID from the JNI APIs.
unsafe impl MemberId for JFieldID {
    fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
        env.get_field_id(desc.cls(), desc.name, desc.sig)
    }
}

/// # Safety
///
/// This fetches the matching ID from the JNI APIs.
unsafe impl MemberId for JStaticFieldID {
    fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
        env.get_static_field_id(desc.cls(), desc.name, desc.sig)
    }
}

/// # Safety
///
/// This fetches the matching ID from the JNI APIs.
unsafe impl MemberId for JMethodID {
    fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
        env.get_method_id(desc.cls(), desc.name, desc.sig)
    }
}

/// # Safety
///
/// This fetches the matching ID from the JNI APIs.
unsafe impl MemberId for JStaticMethodID {
    fn lookup(env: &mut JNIEnv, desc: &MemberDesc<Self>) -> jni::errors::Result<Self> {
        env.get_static_method_id(desc.cls(), desc.name, desc.sig)
    }
}

/// Internal helper to ignore the poison state of `LockResult`.
///
/// The poison state occurs when a panic occurs during the lock's critical section. This means that
/// the invariants of the locked data that were protected by the lock may be broken. When this
/// trait is used below, it is used in scenarios where the locked data does not have invariants
/// that can be broken in this way. In these cases, the possibly-poisoned lock is being used purely
/// for synchronization, so the poison state may be ignored.
trait IgnoreLockPoison {
    type Guard;

    /// Extract the inner `Guard` of this `LockResult`. This ignores whether the lock state is
    /// poisoned or not.
    fn ignore_poison(self) -> Self::Guard;
}

impl<G> IgnoreLockPoison for LockResult<G> {
    type Guard = G;
    fn ignore_poison(self) -> Self::Guard {
        self.unwrap_or_else(|poison| poison.into_inner())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    const DESC: &str = "com/example/Foo";
    static FOO: ClassDesc = ClassDesc::new(DESC);

    static FIELD: FieldDesc = FOO.field("foo", "I");
    static STATIC_FIELD: StaticFieldDesc = FOO.static_field("sfoo", "J");
    static CONSTRUCTOR: MethodDesc = FOO.constructor("(I)V");
    static METHOD: MethodDesc = FOO.method("mfoo", "()Z");
    static STATIC_METHOD: StaticMethodDesc = FOO.static_method("smfoo", "()I");

    #[test]
    fn class_desc_created_properly() {
        assert_eq!(DESC, FOO.descriptor);
        assert!(FOO.cls.read().ignore_poison().is_none());
    }

    #[test]
    fn field_desc_created_properly() {
        assert!(std::ptr::eq(&FOO, FIELD.cls()));
        assert_eq!("foo", FIELD.name);
        assert_eq!("I", FIELD.sig);
    }

    #[test]
    fn static_field_desc_created_properly() {
        assert!(std::ptr::eq(&FOO, STATIC_FIELD.cls()));
        assert_eq!("sfoo", STATIC_FIELD.name);
        assert_eq!("J", STATIC_FIELD.sig);
    }

    #[test]
    fn constructor_desc_created_properly() {
        assert!(std::ptr::eq(&FOO, CONSTRUCTOR.cls()));
        assert_eq!("<init>", CONSTRUCTOR.name);
        assert_eq!("(I)V", CONSTRUCTOR.sig);
    }

    #[test]
    fn method_desc_created_properly() {
        assert!(std::ptr::eq(&FOO, METHOD.cls()));
        assert_eq!("mfoo", METHOD.name);
        assert_eq!("()Z", METHOD.sig);
    }

    #[test]
    fn static_method_desc_created_properly() {
        assert!(std::ptr::eq(&FOO, STATIC_METHOD.cls()));
        assert_eq!("smfoo", STATIC_METHOD.name);
        assert_eq!("()I", STATIC_METHOD.sig);
    }
}
