// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.example.jni_generator;

import android.graphics.Rect;

import org.chromium.base.annotations.AccessedByNative;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.CalledByNativeUnchecked;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeCall;
import org.chromium.base.annotations.NativeClassQualifiedName;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

// This class serves as a reference test for the bindings generator, and as example documentation
// for how to use the jni generator.
// The C++ counter-part is sample_for_tests.cc.
// jni_generator/BUILD.gn has a jni_generator_tests target that will:
//   * Generate a header file for the JNI bindings based on this file.
//   * Generate a header file containing registration methods required to use C++ methods from this
//     file.
//   * Compile sample_for_tests.cc using the generated header file.
//   * link a native executable to prove the generated header + cc file are self-contained.
// All comments are informational only, and are ignored by the jni generator.
//
// This JNINamespace annotation indicates that all native methods should be
// generated inside this namespace, including the native class that this
// object binds to.
@JNINamespace("base::android")
class SampleForTests {
    // Classes can store their C++ pointer counterpart as an int that is normally initialized by
    // calling out a nativeInit() function. Replace "CPPClass" with your particular class name!
    long mNativeCPPObject;

    // You can define methods and attributes on the java class just like any other.
    // Methods without the @CalledByNative annotation won't be exposed to JNI.
    public SampleForTests() {
    }

    public void startExample() {
        // Calls C++ Init(...) method and holds a pointer to the C++ class.
        mNativeCPPObject = nativeInit("myParam");
    }

    public void doStuff() {
        // This will call CPPClass::Method() using nativePtr as a pointer to the object. This must
        // be done to:
        // * avoid leaks.
        // * using finalizers are not allowed to destroy the cpp class.
        nativeMethod(mNativeCPPObject);
    }

    public void finishExample() {
        // We're done, so let's destroy nativePtr object.
        nativeDestroy(mNativeCPPObject);
    }

    // ---------------------------------------------------------------------------------------------
    // The following methods demonstrate exporting Java methods for invocation from C++ code.
    // Java functions are mapping into C global functions by prefixing the method name with
    // "Java_<Class>_"
    // This is triggered by the @CalledByNative annotation; the methods may be named as you wish.

    // Exported to C++ as:
    // Java_SampleForTests_javaMethod(JNIEnv* env, jobject caller, jint foo, jint bar)
    // Typically the C++ code would have obtained the jobject via the Init() call described above.
    @CalledByNative
    public int javaMethod(int foo, int bar) {
        return 0;
    }

    // Exported to C++ as Java_SampleForTests_staticJavaMethod(JNIEnv* env)
    // Note no jobject argument, as it is static.
    @CalledByNative
    public static boolean staticJavaMethod() {
        return true;
    }

    // No prefix, so this method is package private. It will still be exported.
    @CalledByNative
    void packagePrivateJavaMethod() {
    }

    // Method signature with generics in params.
    @CalledByNative
    public void methodWithGenericParams(
            Map<String, Map<String, String>> foo, LinkedList<Integer> bar) {}

    // Constructors will be exported to C++ as:
    // Java_SampleForTests_Constructor(JNIEnv* env, jint foo, jint bar)
    @CalledByNative
    public SampleForTests(int foo, int bar) {}

    // Note the "Unchecked" suffix. By default, @CalledByNative will always generate bindings that
    // call CheckException(). With "@CalledByNativeUnchecked", the client C++ code is responsible to
    // call ClearException() and act as appropriate.
    // See more details at the "@CalledByNativeUnchecked" annotation.
    @CalledByNativeUnchecked
    void methodThatThrowsException() throws Exception {}

    // The generator is not confused by inline comments:
    // @CalledByNative void thisShouldNotAppearInTheOutput();
    // @CalledByNativeUnchecked public static void neitherShouldThis(int foo);

    /**
     * The generator is not confused by block comments:
     * @CalledByNative void thisShouldNotAppearInTheOutputEither();
     * @CalledByNativeUnchecked public static void andDefinitelyNotThis(int foo);
     */

    // String constants that look like comments don't confuse the generator:
    private String mArrgh = "*/*";

    private @interface SomeAnnotation {}

    // The generator is not confused by @Annotated parameters.
    @CalledByNative
    void javaMethodWithAnnotatedParam(@SomeAnnotation int foo) {
    }

    // ---------------------------------------------------------------------------------------------
    // Java fields which are accessed from C++ code only must be annotated with @AccessedByNative to
    // prevent them being eliminated when unreferenced code is stripped.
    @AccessedByNative
    private int mJavaField;

    // ---------------------------------------------------------------------------------------------
    // The following methods demonstrate declaring methods to call into C++ from Java.
    // The generator detects the "native" and "static" keywords, the type and name of the first
    // parameter, and the "native" prefix to the function name to determine the C++ function
    // signatures. Besides these constraints the methods can be freely named.

    // This declares a C++ function which the application code must implement:
    // static jint Init(JNIEnv* env, jobject caller);
    // The jobject parameter refers back to this java side object instance.
    // The implementation must return the pointer to the C++ object cast to jint.
    // The caller of this method should store it, and supply it as a the nativeCPPClass param to
    // subsequent native method calls (see the methods below that take an "int native..." as first
    // param).
    private native long nativeInit(String param);

    // This defines a function binding to the associated C++ class member function. The name is
    // derived from |nativeDestroy| and |nativeCPPClass| to arrive at CPPClass::Destroy() (i.e.
    // native prefixes stripped).
    //
    // The |nativeCPPClass| is automatically cast to type CPPClass*, in order to obtain the object
    // on
    // which to invoke the member function. Replace "CPPClass" with your particular class name!
    private native void nativeDestroy(long nativeCPPClass);

    // This declares a C++ function which the application code must implement:
    // static jdouble GetDoubleFunction(JNIEnv* env, jobject caller);
    // The jobject parameter refers back to this java side object instance.
    private native double nativeGetDoubleFunction();

    // Similar to nativeGetDoubleFunction(), but here the C++ side will receive a jclass rather than
    // jobject param, as the function is declared static.
    private static native float nativeGetFloatFunction();

    // This function takes a non-POD datatype. We have a list mapping them to their full classpath
    // in jni_generator.py JavaParamToJni. If you require a new datatype, make sure you add to that
    // function.
    private native void nativeSetNonPODDatatype(Rect rect);

    // This declares a C++ function which the application code must implement:
    // static ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, jobject caller);
    // The jobject parameter refers back to this java side object instance.
    // Note that it returns a ScopedJavaLocalRef<jobject> so that you don' have to worry about
    // deleting the JNI local reference. This is similar with Strings and arrays.
    private native Object nativeGetNonPODDatatype();

    // Similar to nativeDestroy above, this will cast nativeCPPClass into pointer of CPPClass type
    // and call its Method member function. Replace "CPPClass" with your particular class name!
    private native int nativeMethod(long nativeCPPClass);

    // Similar to nativeMethod above, but here the C++ fully qualified class name is taken from the
    // annotation rather than parameter name, which can thus be chosen freely.
    @NativeClassQualifiedName("CPPClass::InnerClass")
    private native double nativeMethodOtherP0(long nativePtr);

    // This "struct" will be created by the native side using |createInnerStructA|,
    // and used by the java-side somehow.
    // Note that |@CalledByNative| has to contain the inner class name.
    static class InnerStructA {
        private final long mLong;
        private final int mInt;
        private final String mString;

        private InnerStructA(long l, int i, String s) {
            mLong = l;
            mInt = i;
            mString = s;
        }

        @CalledByNative("InnerStructA")
        private static InnerStructA create(long l, int i, String s) {
            return new InnerStructA(l, i, s);
        }
    }

    private List<InnerStructA> mListInnerStructA = new ArrayList<InnerStructA>();

    @CalledByNative
    private void addStructA(InnerStructA a) {
        // Called by the native side to append another element.
        mListInnerStructA.add(a);
    }

    @CalledByNative
    private void iterateAndDoSomething() {
        Iterator<InnerStructA> it = mListInnerStructA.iterator();
        while (it.hasNext()) {
            InnerStructA element = it.next();
            // Now, do something with element.
        }
        // Done, clear the list.
        mListInnerStructA.clear();
    }

    // This "struct" will be created by the java side passed to native, which
    // will use its getters.
    // Note that |@CalledByNative| has to contain the inner class name.
    static class InnerStructB {
        private final long mKey;
        private final String mValue;

        private InnerStructB(long k, String v) {
            mKey = k;
            mValue = v;
        }

        @CalledByNative("InnerStructB")
        private long getKey() {
            return mKey;
        }

        @CalledByNative("InnerStructB")
        private String getValue() {
            return mValue;
        }
    }

    List<InnerStructB> mListInnerStructB = new ArrayList<InnerStructB>();

    void iterateAndDoSomethingWithMap() {
        Iterator<InnerStructB> it = mListInnerStructB.iterator();
        while (it.hasNext()) {
            InnerStructB element = it.next();
            // Now, do something with element.
            nativeAddStructB(mNativeCPPObject, element);
        }
        nativeIterateAndDoSomethingWithStructB(mNativeCPPObject);
    }

    native void nativeAddStructB(long nativeCPPClass, InnerStructB b);
    native void nativeIterateAndDoSomethingWithStructB(long nativeCPPClass);
    native String nativeReturnAString(long nativeCPPClass);

    // This inner class shows how to annotate native methods on inner classes.
    static class InnerClass {
        @NativeCall("InnerClass")
        private static native int nativeGetInnerIntFunction();
    }

    interface InnerInterface {}
    enum InnerEnum {}

    @CalledByNative
    static InnerInterface getInnerInterface() {
        return null;
    }

    @CalledByNative
    static InnerEnum getInnerEnum() {
        return null;
    }
}
