// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include "starboard/android/shared/platform_service.h"

#include <memory>

#include "starboard/android/shared/jni_env_ext.h"
#include "starboard/android/shared/jni_utils.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/extension/platform_service.h"

typedef struct CobaltExtensionPlatformServicePrivate {
  void* context;
  ReceiveMessageCallback receive_callback;
  const char* name;
  jobject cobalt_service;

  ~CobaltExtensionPlatformServicePrivate() {
    if (name) {
      delete name;
    }
    if (cobalt_service) {
      starboard::android::shared::JniEnvExt::Get()->DeleteGlobalRef(
          cobalt_service);
    }
  }
} CobaltExtensionPlatformServicePrivate;

namespace starboard {
namespace android {
namespace shared {

namespace {

using starboard::android::shared::JniEnvExt;
using starboard::android::shared::ScopedLocalJavaRef;

bool Has(const char* name) {
  JniEnvExt* env = JniEnvExt::Get();
  ScopedLocalJavaRef<jstring> j_name(env->NewStringStandardUTFOrAbort(name));
  jboolean j_has = env->CallStarboardBooleanMethodOrAbort(
      "hasCobaltService", "(Ljava/lang/String;)Z", j_name.Get());
  return j_has;
}

CobaltExtensionPlatformService Open(void* context,
                                    const char* name,
                                    ReceiveMessageCallback receive_callback) {
  SB_DCHECK(context);
  JniEnvExt* env = JniEnvExt::Get();

  if (!Has(name)) {
    SB_LOG(ERROR) << "Can't open Service " << name;
    return kCobaltExtensionPlatformServiceInvalid;
  }
  CobaltExtensionPlatformService service =
      new CobaltExtensionPlatformServicePrivate(
          {context, receive_callback, name});
  ScopedLocalJavaRef<jstring> j_name(env->NewStringStandardUTFOrAbort(name));
  jobject cobalt_service = env->CallStarboardObjectMethodOrAbort(
      "openCobaltService",
      "(JLjava/lang/String;)Ldev/cobalt/coat/CobaltService;",
      reinterpret_cast<jlong>(service), j_name.Get());
  if (!cobalt_service) {
    delete static_cast<CobaltExtensionPlatformServicePrivate*>(service);
    return kCobaltExtensionPlatformServiceInvalid;
  }
  service->cobalt_service = env->ConvertLocalRefToGlobalRef(cobalt_service);
  return service;
}

void Close(CobaltExtensionPlatformService service) {
  JniEnvExt* env = JniEnvExt::Get();
  env->CallVoidMethodOrAbort(service->cobalt_service, "onClose", "()V");
  ScopedLocalJavaRef<jstring> j_name(
      env->NewStringStandardUTFOrAbort(service->name));
  env->CallStarboardVoidMethodOrAbort("closeCobaltService",
                                      "(Ljava/lang/String;)V", j_name.Get());
  delete static_cast<CobaltExtensionPlatformServicePrivate*>(service);
}

void* Send(CobaltExtensionPlatformService service,
           void* data,
           uint64_t length,
           uint64_t* output_length,
           bool* invalid_state) {
  SB_DCHECK(data);
  SB_DCHECK(output_length);
  SB_DCHECK(invalid_state);

  JniEnvExt* env = JniEnvExt::Get();
  ScopedLocalJavaRef<jbyteArray> data_byte_array;
  data_byte_array.Reset(
      env->NewByteArrayFromRaw(reinterpret_cast<const jbyte*>(data), length));
  ScopedLocalJavaRef<jobject> j_response_from_client(
      static_cast<jbyteArray>(env->CallObjectMethodOrAbort(
          service->cobalt_service, "receiveFromClient",
          "([B)Ldev/cobalt/coat/CobaltService$ResponseToClient;",
          data_byte_array.Get())));
  if (!j_response_from_client) {
    *invalid_state = true;
    *output_length = 0;
    return 0;
  }
  *invalid_state = env->GetBooleanFieldOrAbort(j_response_from_client.Get(),
                                               "invalidState", "Z");
  ScopedLocalJavaRef<jbyteArray> j_out_data_array(static_cast<jbyteArray>(
      env->GetObjectFieldOrAbort(j_response_from_client.Get(), "data", "[B")));
  *output_length = env->GetArrayLength(j_out_data_array.Get());
  char* output = new char[*output_length];
  env->GetByteArrayRegion(j_out_data_array.Get(), 0, *output_length,
                          reinterpret_cast<jbyte*>(output));
  return output;
}

const CobaltExtensionPlatformServiceApi kPlatformServiceApi = {
    kCobaltExtensionPlatformServiceName,
    1,  // API version that's implemented.
    &Has,
    &Open,
    &Close,
    &Send};

}  // namespace

extern "C" SB_EXPORT_PLATFORM void
Java_dev_cobalt_coat_CobaltService_nativeSendToClient(JniEnvExt* env,
                                                      jobject jcaller,
                                                      jlong nativeService,
                                                      jbyteArray j_data) {
  CobaltExtensionPlatformService service =
      reinterpret_cast<CobaltExtensionPlatformService>(nativeService);
  if (!CobaltExtensionPlatformServiceIsValid(service)) {
    SB_LOG(WARNING) << "Trying to send message through platform service when "
                       "the service is already closed";
    return;
  }

  jsize length = env->GetArrayLength(j_data);
  std::unique_ptr<char[]> data(new char[length]);
  env->GetByteArrayRegion(j_data, 0, length,
                          reinterpret_cast<jbyte*>(data.get()));

  service->receive_callback(service->context, data.get(), length);
}

const void* GetPlatformServiceApi() {
  return &kPlatformServiceApi;
}

}  // namespace shared
}  // namespace android
}  // namespace starboard
