/*
 *  Copyright 2017 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.
 */

#include <memory>

#include <limits>

#include "api/datachannelinterface.h"
#include "rtc_base/logging.h"
#include "rtc_base/ptr_util.h"
#include "sdk/android/generated_peerconnection_jni/jni/DataChannel_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/pc/datachannel.h"

namespace webrtc {
namespace jni {

namespace {
// Adapter for a Java DataChannel$Observer presenting a C++ DataChannelObserver
// and dispatching the callback from C++ back to Java.
class DataChannelObserverJni : public DataChannelObserver {
 public:
  DataChannelObserverJni(JNIEnv* jni, const JavaRef<jobject>& j_observer);
  virtual ~DataChannelObserverJni() {}

  void OnBufferedAmountChange(uint64_t previous_amount) override;
  void OnStateChange() override;
  void OnMessage(const DataBuffer& buffer) override;

 private:
  const ScopedJavaGlobalRef<jobject> j_observer_global_;
};

DataChannelObserverJni::DataChannelObserverJni(
    JNIEnv* jni,
    const JavaRef<jobject>& j_observer)
    : j_observer_global_(jni, j_observer) {}

void DataChannelObserverJni::OnBufferedAmountChange(uint64_t previous_amount) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onBufferedAmountChange(env, j_observer_global_,
                                       previous_amount);
}

void DataChannelObserverJni::OnStateChange() {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onStateChange(env, j_observer_global_);
}

void DataChannelObserverJni::OnMessage(const DataBuffer& buffer) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  ScopedJavaLocalRef<jobject> byte_buffer = NewDirectByteBuffer(
      env, const_cast<char*>(buffer.data.data<char>()), buffer.data.size());
  ScopedJavaLocalRef<jobject> j_buffer =
      Java_Buffer_Constructor(env, byte_buffer, buffer.binary);
  Java_Observer_onMessage(env, j_observer_global_, j_buffer);
}

DataChannelInterface* ExtractNativeDC(JNIEnv* jni,
                                      const JavaParamRef<jobject>& j_dc) {
  return reinterpret_cast<DataChannelInterface*>(
      Java_DataChannel_getNativeDataChannel(jni, j_dc));
}

}  // namespace

DataChannelInit JavaToNativeDataChannelInit(JNIEnv* env,
                                            const JavaRef<jobject>& j_init) {
  DataChannelInit init;
  init.ordered = Java_Init_getOrdered(env, j_init);
  init.maxRetransmitTime = Java_Init_getMaxRetransmitTimeMs(env, j_init);
  init.maxRetransmits = Java_Init_getMaxRetransmits(env, j_init);
  init.protocol = JavaToStdString(env, Java_Init_getProtocol(env, j_init));
  init.negotiated = Java_Init_getNegotiated(env, j_init);
  init.id = Java_Init_getId(env, j_init);
  return init;
}

ScopedJavaLocalRef<jobject> WrapNativeDataChannel(
    JNIEnv* env,
    rtc::scoped_refptr<DataChannelInterface> channel) {
  if (!channel)
    return nullptr;
  // Channel is now owned by Java object, and will be freed from there.
  return Java_DataChannel_Constructor(env, jlongFromPointer(channel.release()));
}

static jlong JNI_DataChannel_RegisterObserver(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_dc,
    const JavaParamRef<jobject>& j_observer) {
  auto observer = rtc::MakeUnique<DataChannelObserverJni>(jni, j_observer);
  ExtractNativeDC(jni, j_dc)->RegisterObserver(observer.get());
  return jlongFromPointer(observer.release());
}

static void JNI_DataChannel_UnregisterObserver(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_dc,
    jlong native_observer) {
  ExtractNativeDC(jni, j_dc)->UnregisterObserver();
  delete reinterpret_cast<DataChannelObserverJni*>(native_observer);
}

static ScopedJavaLocalRef<jstring> JNI_DataChannel_Label(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_dc) {
  return NativeToJavaString(jni, ExtractNativeDC(jni, j_dc)->label());
}

static jint JNI_DataChannel_Id(JNIEnv* jni, const JavaParamRef<jobject>& j_dc) {
  int id = ExtractNativeDC(jni, j_dc)->id();
  RTC_CHECK_LE(id, std::numeric_limits<int32_t>::max())
      << "id overflowed jint!";
  return static_cast<jint>(id);
}

static ScopedJavaLocalRef<jobject> JNI_DataChannel_State(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_dc) {
  return Java_State_fromNativeIndex(jni, ExtractNativeDC(jni, j_dc)->state());
}

static jlong JNI_DataChannel_BufferedAmount(JNIEnv* jni,
                                            const JavaParamRef<jobject>& j_dc) {
  uint64_t buffered_amount = ExtractNativeDC(jni, j_dc)->buffered_amount();
  RTC_CHECK_LE(buffered_amount, std::numeric_limits<int64_t>::max())
      << "buffered_amount overflowed jlong!";
  return static_cast<jlong>(buffered_amount);
}

static void JNI_DataChannel_Close(JNIEnv* jni,
                                  const JavaParamRef<jobject>& j_dc) {
  ExtractNativeDC(jni, j_dc)->Close();
}

static jboolean JNI_DataChannel_Send(JNIEnv* jni,
                                     const JavaParamRef<jobject>& j_dc,
                                     const JavaParamRef<jbyteArray>& data,
                                     jboolean binary) {
  jbyte* bytes = jni->GetByteArrayElements(data.obj(), nullptr);
  bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
      rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data.obj())), binary));
  jni->ReleaseByteArrayElements(data.obj(), bytes, JNI_ABORT);
  return ret;
}

}  // namespace jni
}  // namespace webrtc
