/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "BluetoothHidDeviceServiceJni"

#define LOG_NDEBUG 0

#include "android_runtime/AndroidRuntime.h"
#include "com_android_bluetooth.h"
#include "hardware/bt_hd.h"
#include "utils/Log.h"

#include <string.h>

namespace android {

static jmethodID method_onApplicationStateChanged;
static jmethodID method_onConnectStateChanged;
static jmethodID method_onGetReport;
static jmethodID method_onSetReport;
static jmethodID method_onSetProtocol;
static jmethodID method_onInterruptData;
static jmethodID method_onVirtualCableUnplug;

static const bthd_interface_t* sHiddIf = NULL;
static jobject mCallbacksObj = NULL;

static jbyteArray marshall_bda(RawAddress* bd_addr) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return NULL;

  jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
  if (!addr) {
    ALOGE("Fail to new jbyteArray bd addr");
    return NULL;
  }
  sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress),
                                   (jbyte*)bd_addr);
  return addr;
}

static void application_state_callback(RawAddress* bd_addr,
                                       bthd_application_state_t state) {
  jboolean registered = JNI_FALSE;

  CallbackEnv sCallbackEnv(__func__);

  if (state == BTHD_APP_STATE_REGISTERED) {
    registered = JNI_TRUE;
  }

  ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), NULL);

  if (bd_addr) {
    addr.reset(marshall_bda(bd_addr));
    if (!addr.get()) {
      ALOGE("%s: failed to allocate storage for bt_addr", __FUNCTION__);
      return;
    }
  }

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onApplicationStateChanged,
                               addr.get(), registered);
}

static void connection_state_callback(RawAddress* bd_addr,
                                      bthd_connection_state_t state) {
  CallbackEnv sCallbackEnv(__func__);

  ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
  if (!addr.get()) {
    ALOGE("%s: failed to allocate storage for bt_addr", __FUNCTION__);
    return;
  }

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged,
                               addr.get(), (jint)state);
}

static void get_report_callback(uint8_t type, uint8_t id,
                                uint16_t buffer_size) {
  CallbackEnv sCallbackEnv(__func__);

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetReport, type, id,
                               buffer_size);
}

static void set_report_callback(uint8_t type, uint8_t id, uint16_t len,
                                uint8_t* p_data) {
  CallbackEnv sCallbackEnv(__func__);

  ScopedLocalRef<jbyteArray> data(sCallbackEnv.get(),
                                  sCallbackEnv->NewByteArray(len));
  if (!data.get()) {
    ALOGE("%s: failed to allocate storage for report data", __FUNCTION__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(data.get(), 0, len, (jbyte*)p_data);

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSetReport, (jbyte)type,
                               (jbyte)id, data.get());
}

static void set_protocol_callback(uint8_t protocol) {
  CallbackEnv sCallbackEnv(__func__);

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSetProtocol, protocol);
}

static void intr_data_callback(uint8_t report_id, uint16_t len,
                               uint8_t* p_data) {
  CallbackEnv sCallbackEnv(__func__);

  ScopedLocalRef<jbyteArray> data(sCallbackEnv.get(),
                                  sCallbackEnv->NewByteArray(len));
  if (!data.get()) {
    ALOGE("%s: failed to allocate storage for report data", __FUNCTION__);
    return;
  }
  sCallbackEnv->SetByteArrayRegion(data.get(), 0, len, (jbyte*)p_data);

  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInterruptData,
                               (jbyte)report_id, data.get());
}

static void vc_unplug_callback(void) {
  CallbackEnv sCallbackEnv(__func__);
  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVirtualCableUnplug);
}

static bthd_callbacks_t sHiddCb = {
    sizeof(sHiddCb),

    application_state_callback,
    connection_state_callback,
    get_report_callback,
    set_report_callback,
    set_protocol_callback,
    intr_data_callback,
    vc_unplug_callback,
};

static void classInitNative(JNIEnv* env, jclass clazz) {
  ALOGV("%s: done", __FUNCTION__);

  method_onApplicationStateChanged =
      env->GetMethodID(clazz, "onApplicationStateChanged", "([BZ)V");
  method_onConnectStateChanged =
      env->GetMethodID(clazz, "onConnectStateChanged", "([BI)V");
  method_onGetReport = env->GetMethodID(clazz, "onGetReport", "(BBS)V");
  method_onSetReport = env->GetMethodID(clazz, "onSetReport", "(BB[B)V");
  method_onSetProtocol = env->GetMethodID(clazz, "onSetProtocol", "(B)V");
  method_onInterruptData = env->GetMethodID(clazz, "onInterruptData", "(B[B)V");
  method_onVirtualCableUnplug =
      env->GetMethodID(clazz, "onVirtualCableUnplug", "()V");
}

static void initNative(JNIEnv* env, jobject object) {
  const bt_interface_t* btif;
  bt_status_t status;

  ALOGV("%s enter", __FUNCTION__);

  if ((btif = getBluetoothInterface()) == NULL) {
    ALOGE("Cannot obtain BT interface");
    return;
  }

  if (sHiddIf != NULL) {
    ALOGW("Cleaning up interface");
    sHiddIf->cleanup();
    sHiddIf = NULL;
  }

  if (mCallbacksObj != NULL) {
    ALOGW("Cleaning up callback object");
    env->DeleteGlobalRef(mCallbacksObj);
    mCallbacksObj = NULL;
  }

  if ((sHiddIf = (bthd_interface_t*)btif->get_profile_interface(
           BT_PROFILE_HIDDEV_ID)) == NULL) {
    ALOGE("Cannot obtain interface");
    return;
  }

  if ((status = sHiddIf->init(&sHiddCb)) != BT_STATUS_SUCCESS) {
    ALOGE("Failed to initialize interface (%d)", status);
    sHiddIf = NULL;
    return;
  }

  mCallbacksObj = env->NewGlobalRef(object);

  ALOGV("%s done", __FUNCTION__);
}

static void cleanupNative(JNIEnv* env, jobject object) {
  ALOGV("%s enter", __FUNCTION__);

  if (sHiddIf != NULL) {
    ALOGI("Cleaning up interface");
    sHiddIf->cleanup();
    sHiddIf = NULL;
  }

  if (mCallbacksObj != NULL) {
    ALOGI("Cleaning up callback object");
    env->DeleteGlobalRef(mCallbacksObj);
    mCallbacksObj = NULL;
  }

  ALOGV("%s done", __FUNCTION__);
}

static void fill_qos(JNIEnv* env, jintArray in, bthd_qos_param_t* out) {
  // set default values
  out->service_type = 0x01;  // best effort
  out->token_rate = out->token_bucket_size = out->peak_bandwidth =
      0;                                                    // don't care
  out->access_latency = out->delay_variation = 0xffffffff;  // don't care

  if (in == NULL) return;

  jsize len = env->GetArrayLength(in);

  if (len != 6) return;

  uint32_t* buf = (uint32_t*)calloc(len, sizeof(uint32_t));

  if (buf == NULL) return;

  env->GetIntArrayRegion(in, 0, len, (jint*)buf);

  out->service_type = (uint8_t)buf[0];
  out->token_rate = buf[1];
  out->token_bucket_size = buf[2];
  out->peak_bandwidth = buf[3];
  out->access_latency = buf[4];
  out->delay_variation = buf[5];

  free(buf);
}

static jboolean registerAppNative(JNIEnv* env, jobject thiz, jstring name,
                                  jstring description, jstring provider,
                                  jbyte subclass, jbyteArray descriptors,
                                  jintArray p_in_qos, jintArray p_out_qos) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;
  bthd_app_param_t app_param;
  bthd_qos_param_t in_qos;
  bthd_qos_param_t out_qos;
  jsize size;
  uint8_t* data;

  size = env->GetArrayLength(descriptors);
  data = (uint8_t*)malloc(size);

  if (data != NULL) {
    env->GetByteArrayRegion(descriptors, 0, size, (jbyte*)data);

    app_param.name = env->GetStringUTFChars(name, NULL);
    app_param.description = env->GetStringUTFChars(description, NULL);
    app_param.provider = env->GetStringUTFChars(provider, NULL);
    app_param.subclass = subclass;
    app_param.desc_list = data;
    app_param.desc_list_len = size;

    fill_qos(env, p_in_qos, &in_qos);
    fill_qos(env, p_out_qos, &out_qos);

    bt_status_t ret = sHiddIf->register_app(&app_param, &in_qos, &out_qos);

    ALOGV("%s: register_app() returned %d", __FUNCTION__, ret);

    if (ret == BT_STATUS_SUCCESS) {
      result = JNI_TRUE;
    }

    env->ReleaseStringUTFChars(name, app_param.name);
    env->ReleaseStringUTFChars(description, app_param.description);
    env->ReleaseStringUTFChars(provider, app_param.provider);

    free(data);
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean unregisterAppNative(JNIEnv* env, jobject thiz) {
  ALOGV("%s enter", __FUNCTION__);

  jboolean result = JNI_FALSE;

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  bt_status_t ret = sHiddIf->unregister_app();

  ALOGV("%s: unregister_app() returned %d", __FUNCTION__, ret);

  if (ret == BT_STATUS_SUCCESS) {
    result = JNI_TRUE;
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean sendReportNative(JNIEnv* env, jobject thiz, jint id,
                                 jbyteArray data) {
  jboolean result = JNI_FALSE;

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jsize size;
  uint8_t* buf;

  size = env->GetArrayLength(data);
  buf = (uint8_t*)malloc(size);

  if (buf != NULL) {
    env->GetByteArrayRegion(data, 0, size, (jbyte*)buf);

    bt_status_t ret =
        sHiddIf->send_report(BTHD_REPORT_TYPE_INTRDATA, id, size, buf);

    if (ret == BT_STATUS_SUCCESS) {
      result = JNI_TRUE;
    }

    free(buf);
  }

  return result;
}

static jboolean replyReportNative(JNIEnv* env, jobject thiz, jbyte type,
                                  jbyte id, jbyteArray data) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;
  jsize size;
  uint8_t* buf;

  size = env->GetArrayLength(data);
  buf = (uint8_t*)malloc(size);

  if (buf != NULL) {
    int report_type = (type & 0x03);
    env->GetByteArrayRegion(data, 0, size, (jbyte*)buf);

    bt_status_t ret =
        sHiddIf->send_report((bthd_report_type_t)report_type, id, size, buf);

    ALOGV("%s: send_report() returned %d", __FUNCTION__, ret);

    if (ret == BT_STATUS_SUCCESS) {
      result = JNI_TRUE;
    }

    free(buf);
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean reportErrorNative(JNIEnv* env, jobject thiz, jbyte error) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;

  bt_status_t ret = sHiddIf->report_error(error);

  ALOGV("%s: report_error() returned %d", __FUNCTION__, ret);

  if (ret == BT_STATUS_SUCCESS) {
    result = JNI_TRUE;
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean unplugNative(JNIEnv* env, jobject thiz) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;

  bt_status_t ret = sHiddIf->virtual_cable_unplug();

  ALOGV("%s: virtual_cable_unplug() returned %d", __FUNCTION__, ret);

  if (ret == BT_STATUS_SUCCESS) {
    result = JNI_TRUE;
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean connectNative(JNIEnv* env, jobject thiz, jbyteArray address) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;

  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    ALOGE("Bluetooth device address null");
    return JNI_FALSE;
  }

  bt_status_t ret = sHiddIf->connect((RawAddress*)addr);

  ALOGV("%s: connect() returned %d", __FUNCTION__, ret);

  if (ret == BT_STATUS_SUCCESS) {
    result = JNI_TRUE;
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static jboolean disconnectNative(JNIEnv* env, jobject thiz) {
  ALOGV("%s enter", __FUNCTION__);

  if (!sHiddIf) {
    ALOGE("%s: Failed to get the Bluetooth HIDD Interface", __func__);
    return JNI_FALSE;
  }

  jboolean result = JNI_FALSE;

  bt_status_t ret = sHiddIf->disconnect();

  ALOGV("%s: disconnect() returned %d", __FUNCTION__, ret);

  if (ret == BT_STATUS_SUCCESS) {
    result = JNI_TRUE;
  }

  ALOGV("%s done (%d)", __FUNCTION__, result);

  return result;
}

static JNINativeMethod sMethods[] = {
    {"classInitNative", "()V", (void*)classInitNative},
    {"initNative", "()V", (void*)initNative},
    {"cleanupNative", "()V", (void*)cleanupNative},
    {"registerAppNative",
     "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;B[B[I[I)Z",
     (void*)registerAppNative},
    {"unregisterAppNative", "()Z", (void*)unregisterAppNative},
    {"sendReportNative", "(I[B)Z", (void*)sendReportNative},
    {"replyReportNative", "(BB[B)Z", (void*)replyReportNative},
    {"reportErrorNative", "(B)Z", (void*)reportErrorNative},
    {"unplugNative", "()Z", (void*)unplugNative},
    {"connectNative", "([B)Z", (void*)connectNative},
    {"disconnectNative", "()Z", (void*)disconnectNative},
};

int register_com_android_bluetooth_hid_device(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env, "com/android/bluetooth/hid/HidDeviceNativeInterface", sMethods,
      NELEM(sMethods));
}
}  // namespace android
