/*
 *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Android's FindClass() is tricky because the app-specific ClassLoader is not
// consulted when there is no app-specific frame on the stack (i.e. when called
// from a thread created from native C++ code). These helper functions provide a
// workaround for this.
// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass

#ifndef SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
#define SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_

#include <jni.h>
#include <map>
#include <string>
#include <vector>

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/thread_checker.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"

// Abort the process if |jni| has a Java exception pending.
// This macros uses the comma operator to execute ExceptionDescribe
// and ExceptionClear ignoring their return values and sending ""
// to the error stream.
#define CHECK_EXCEPTION(jni)        \
  RTC_CHECK(!jni->ExceptionCheck()) \
      << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")

namespace webrtc {

// ---------------
// -- Utilities --
// ---------------

// Provides a convenient way to iterate over a Java Iterable using the
// C++ range-for loop.
// E.g. for (jobject value : Iterable(jni, j_iterable)) { ... }
// Note: Since Java iterators cannot be duplicated, the iterator class is not
// copyable to prevent creating multiple C++ iterators that refer to the same
// Java iterator.
class Iterable {
 public:
  Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable);
  Iterable(Iterable&& other);

  ~Iterable();

  class Iterator {
   public:
    // Creates an iterator representing the end of any collection.
    Iterator();
    // Creates an iterator pointing to the beginning of the specified
    // collection.
    Iterator(JNIEnv* jni, const JavaRef<jobject>& iterable);

    // Move constructor - necessary to be able to return iterator types from
    // functions.
    Iterator(Iterator&& other);

    ~Iterator();

    // Move assignment should not be used.
    Iterator& operator=(Iterator&&) = delete;

    // Advances the iterator one step.
    Iterator& operator++();

    // Removes the element the iterator is pointing to. Must still advance the
    // iterator afterwards.
    void Remove();

    // Provides a way to compare the iterator with itself and with the end
    // iterator.
    // Note: all other comparison results are undefined, just like for C++ input
    // iterators.
    bool operator==(const Iterator& other);
    bool operator!=(const Iterator& other) { return !(*this == other); }
    ScopedJavaLocalRef<jobject>& operator*();

   private:
    bool AtEnd() const;

    JNIEnv* jni_ = nullptr;
    ScopedJavaLocalRef<jobject> iterator_;
    ScopedJavaLocalRef<jobject> value_;
    rtc::ThreadChecker thread_checker_;

    RTC_DISALLOW_COPY_AND_ASSIGN(Iterator);
  };

  Iterable::Iterator begin() { return Iterable::Iterator(jni_, iterable_); }
  Iterable::Iterator end() { return Iterable::Iterator(); }

 private:
  JNIEnv* jni_;
  ScopedJavaLocalRef<jobject> iterable_;

  RTC_DISALLOW_COPY_AND_ASSIGN(Iterable);
};

// Returns true if |obj| == null in Java.
bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj);

// Returns the name of a Java enum.
std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum);

Iterable GetJavaMapEntrySet(JNIEnv* jni, const JavaRef<jobject>& j_map);
ScopedJavaLocalRef<jobject> GetJavaMapEntryKey(JNIEnv* jni,
                                               const JavaRef<jobject>& j_entry);
ScopedJavaLocalRef<jobject> GetJavaMapEntryValue(
    JNIEnv* jni,
    const JavaRef<jobject>& j_entry);

// --------------------------------------------------------
// -- Methods for converting Java types to native types. --
// --------------------------------------------------------

int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long);

absl::optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
                                              const JavaRef<jobject>& boolean);
absl::optional<double> JavaToNativeOptionalDouble(
    JNIEnv* jni,
    const JavaRef<jobject>& j_double);
absl::optional<int32_t> JavaToNativeOptionalInt(
    JNIEnv* jni,
    const JavaRef<jobject>& integer);

// Given a (UTF-16) jstring return a new UTF-8 native string.
std::string JavaToNativeString(JNIEnv* jni, const JavaRef<jstring>& j_string);

template <typename T, typename Convert>
std::vector<T> JavaToNativeVector(JNIEnv* env,
                                  const JavaRef<jobjectArray>& j_container,
                                  Convert convert) {
  std::vector<T> container;
  const size_t size = env->GetArrayLength(j_container.obj());
  container.reserve(size);
  for (size_t i = 0; i < size; ++i) {
    container.emplace_back(convert(
        env, ScopedJavaLocalRef<jobject>(
                 env, env->GetObjectArrayElement(j_container.obj(), i))));
  }
  CHECK_EXCEPTION(env) << "Error during JavaToNativeVector";
  return container;
}

template <typename T, typename Java_T = jobject, typename Convert>
std::vector<T> JavaListToNativeVector(JNIEnv* env,
                                      const JavaRef<jobject>& j_list,
                                      Convert convert) {
  std::vector<T> native_list;
  if (!j_list.is_null()) {
    for (ScopedJavaLocalRef<jobject>& j_item : Iterable(env, j_list)) {
      native_list.emplace_back(
          convert(env, static_java_ref_cast<Java_T>(env, j_item)));
    }
    CHECK_EXCEPTION(env) << "Error during JavaListToNativeVector";
  }
  return native_list;
}

template <typename Key, typename T, typename Convert>
std::map<Key, T> JavaToNativeMap(JNIEnv* env,
                                 const JavaRef<jobject>& j_map,
                                 Convert convert) {
  std::map<Key, T> container;
  for (auto const& j_entry : GetJavaMapEntrySet(env, j_map)) {
    container.emplace(convert(env, GetJavaMapEntryKey(env, j_entry),
                              GetJavaMapEntryValue(env, j_entry)));
  }
  return container;
}

// Converts Map<String, String> to std::map<std::string, std::string>.
std::map<std::string, std::string> JavaToNativeStringMap(
    JNIEnv* env,
    const JavaRef<jobject>& j_map);

// --------------------------------------------------------
// -- Methods for converting native types to Java types. --
// --------------------------------------------------------

ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b);
ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d);
ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i);
ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u);
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni, const char* str);
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
                                               const std::string& str);

ScopedJavaLocalRef<jobject> NativeToJavaDouble(
    JNIEnv* jni,
    const absl::optional<double>& optional_double);
ScopedJavaLocalRef<jobject> NativeToJavaInteger(
    JNIEnv* jni,
    const absl::optional<int32_t>& optional_int);
ScopedJavaLocalRef<jstring> NativeToJavaString(
    JNIEnv* jni,
    const absl::optional<std::string>& str);

// Helper function for converting std::vector<T> into a Java array.
template <typename T, typename Convert>
ScopedJavaLocalRef<jobjectArray> NativeToJavaObjectArray(
    JNIEnv* env,
    const std::vector<T>& container,
    jclass clazz,
    Convert convert) {
  ScopedJavaLocalRef<jobjectArray> j_container(
      env, env->NewObjectArray(container.size(), clazz, nullptr));
  int i = 0;
  for (const T& element : container) {
    env->SetObjectArrayElement(j_container.obj(), i,
                               convert(env, element).obj());
    ++i;
  }
  return j_container;
}

ScopedJavaLocalRef<jbyteArray> NativeToJavaByteArray(
    JNIEnv* env,
    rtc::ArrayView<int8_t> container);
ScopedJavaLocalRef<jintArray> NativeToJavaIntArray(
    JNIEnv* env,
    rtc::ArrayView<int32_t> container);

std::vector<int8_t> JavaToNativeByteArray(JNIEnv* env,
                                          const JavaRef<jbyteArray>& jarray);
std::vector<int32_t> JavaToNativeIntArray(JNIEnv* env,
                                          const JavaRef<jintArray>& jarray);

ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
    JNIEnv* env,
    const std::vector<bool>& container);
ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
    JNIEnv* env,
    const std::vector<double>& container);
ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
    JNIEnv* env,
    const std::vector<int32_t>& container);
ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
    JNIEnv* env,
    const std::vector<int64_t>& container);
ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
    JNIEnv* env,
    const std::vector<std::string>& container);

// This is a helper class for NativeToJavaList(). Use that function instead of
// using this class directly.
class JavaListBuilder {
 public:
  explicit JavaListBuilder(JNIEnv* env);
  ~JavaListBuilder();
  void add(const JavaRef<jobject>& element);
  ScopedJavaLocalRef<jobject> java_list() { return j_list_; }

 private:
  JNIEnv* env_;
  ScopedJavaLocalRef<jobject> j_list_;
};

template <typename C, typename Convert>
ScopedJavaLocalRef<jobject> NativeToJavaList(JNIEnv* env,
                                             const C& container,
                                             Convert convert) {
  JavaListBuilder builder(env);
  for (const auto& e : container)
    builder.add(convert(env, e));
  return builder.java_list();
}

// This is a helper class for NativeToJavaMap(). Use that function instead of
// using this class directly.
class JavaMapBuilder {
 public:
  explicit JavaMapBuilder(JNIEnv* env);
  ~JavaMapBuilder();
  void put(const JavaRef<jobject>& key, const JavaRef<jobject>& value);
  ScopedJavaLocalRef<jobject> GetJavaMap() { return j_map_; }

 private:
  JNIEnv* env_;
  ScopedJavaLocalRef<jobject> j_map_;
};

template <typename C, typename Convert>
ScopedJavaLocalRef<jobject> NativeToJavaMap(JNIEnv* env,
                                            const C& container,
                                            Convert convert) {
  JavaMapBuilder builder(env);
  for (const auto& e : container) {
    const auto key_value_pair = convert(env, e);
    builder.put(key_value_pair.first, key_value_pair.second);
  }
  return builder.GetJavaMap();
}

template <typename C>
ScopedJavaLocalRef<jobject> NativeToJavaStringMap(JNIEnv* env,
                                                  const C& container) {
  JavaMapBuilder builder(env);
  for (const auto& e : container) {
    const auto key_value_pair = std::make_pair(
        NativeToJavaString(env, e.first), NativeToJavaString(env, e.second));
    builder.put(key_value_pair.first, key_value_pair.second);
  }
  return builder.GetJavaMap();
}

// Return a |jlong| that will correctly convert back to |ptr|.  This is needed
// because the alternative (of silently passing a 32-bit pointer to a vararg
// function expecting a 64-bit param) picks up garbage in the high 32 bits.
jlong NativeToJavaPointer(void* ptr);

// ------------------------
// -- Deprecated methods --
// ------------------------

// Deprecated. Use JavaToNativeString.
inline std::string JavaToStdString(JNIEnv* jni,
                                   const JavaRef<jstring>& j_string) {
  return JavaToNativeString(jni, j_string);
}

// Deprecated. Use scoped jobjects instead.
inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
  return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
}

// Deprecated. Use JavaListToNativeVector<std::string, jstring> instead.
// Given a List of (UTF-16) jstrings
// return a new vector of UTF-8 native strings.
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
                                                const JavaRef<jobject>& list);

// Deprecated. Use JavaToNativeStringMap instead.
// Parses Map<String, String> to std::map<std::string, std::string>.
inline std::map<std::string, std::string> JavaToStdMapStrings(
    JNIEnv* jni,
    const JavaRef<jobject>& j_map) {
  return JavaToNativeStringMap(jni, j_map);
}

// Deprecated. Use scoped jobjects instead.
inline std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
                                                              jobject j_map) {
  return JavaToStdMapStrings(jni, JavaParamRef<jobject>(j_map));
}

}  // namespace webrtc

#endif  // SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
