/*
 *  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 <memory>
#include <string>
#include <vector>

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/sequence_checker.h"
#include "rtc_base/checks.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_;
    SequenceChecker 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_
