// Copyright 2010-2014, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// JNI wrapper for SessionHandler.

#include <jni.h>

#include "base/android_jni_proxy.h"
#include "base/android_util.h"
#include "base/mutex.h"
#include "base/scheduler.h"
#include "base/singleton.h"
#include "base/system_util.h"
#include "base/version.h"
#include "converter/connector_interface.h"
#include "dictionary/dictionary_interface.h"
#include "engine/engine_factory.h"
#include "session/commands.pb.h"
#include "session/session_handler.h"
#include "session/session_usage_observer.h"
#include "usage_stats/usage_stats_uploader.h"

#include "data_manager/oss/oss_data_manager.h"
typedef mozc::oss::OssDataManager DataManagerType;

namespace mozc {
namespace jni {
namespace {
jobject g_connection_data_buffer;
jobject g_dictionary_buffer;

// Adapter class to make a SessionHandlerInterface (held by this class)
// singleton.
// Must be accessed via mozc::Singleton<SessionHandlerSingletonAdapter>.
class SessionHandlerSingletonAdapter {
 public:
  SessionHandlerSingletonAdapter()
      : engine_(mozc::EngineFactory::Create()),
        session_handler_(new mozc::SessionHandler(engine_.get())) {}
  ~SessionHandlerSingletonAdapter() {}

  SessionHandlerInterface *getHandler() {
    return session_handler_.get();
  }

 private:
  // Must be defined earlier than session_handler_, which depends on this.
  scoped_ptr<EngineInterface> engine_;
  scoped_ptr<SessionHandlerInterface> session_handler_;

  DISALLOW_COPY_AND_ASSIGN(SessionHandlerSingletonAdapter);
};

void Initialize(
    JavaVM *vm,
    const char *user_profile_directory,
    void *dictionary_address, int dictionary_size,
    void *connection_data_address, int connection_data_size) {
  // First of all, set the user profile directory.
  SystemUtil::SetUserProfileDirectory(user_profile_directory);

#ifdef MOZC_ENABLE_HTTP_CLIENT
  // Initialize Java native callback proxy.
  JavaHttpClientProxy::SetJavaVM(vm);
#endif  // MOZC_ENABLE_HTTP_CLIENT

  // Initialize dictionary data.
  DataManagerType::SetDictionaryData(dictionary_address, dictionary_size);
  DataManagerType::SetConnectionData(connection_data_address,
                                     connection_data_size);

  mozc::Singleton<SessionHandlerSingletonAdapter>::get()->getHandler()
      ->AddObserver(Singleton<session::SessionUsageObserver>::get());

  // Start usage stats timer.
  using usage_stats::UsageStatsUploader;
  mozc::Scheduler::AddJob(Scheduler::JobSetting(
      "UsageStatsTimer",
      UsageStatsUploader::kDefaultScheduleInterval,
      UsageStatsUploader::kDefaultScheduleMaxInterval,
      UsageStatsUploader::kDefaultSchedulerDelay,
      UsageStatsUploader::kDefaultSchedulerRandomDelay,
      &UsageStatsUploader::Send,
      NULL));
}

// Concrete implementation for MozcJni.evalCommand
jbyteArray JNICALL evalCommand(JNIEnv *env,
                               jclass clazz,
                               jbyteArray in_bytes_array) {
  jboolean is_copy = false;
  jbyte *in_bytes = env->GetByteArrayElements(in_bytes_array, &is_copy);
  const jsize in_size = env->GetArrayLength(in_bytes_array);
  mozc::commands::Command command;
  command.ParseFromArray(in_bytes, in_size);
  mozc::Singleton<SessionHandlerSingletonAdapter>::get()->getHandler()
      ->EvalCommand(&command);

  // Use JNI_ABORT because in_bytes is read only.
  env->ReleaseByteArrayElements(in_bytes_array, in_bytes, JNI_ABORT);

  const int out_size = command.ByteSize();
  jbyteArray out_bytes_array = env->NewByteArray(out_size);
  jbyte *out_bytes = env->GetByteArrayElements(out_bytes_array, &is_copy);
  command.SerializeToArray(out_bytes, out_size);

  // Use 0 to copy out_bytes to out_bytes_array.
  env->ReleaseByteArrayElements(out_bytes_array, out_bytes, 0);

  return out_bytes_array;
}

void JNICALL onPostLoad(JNIEnv *env,
                        jclass clazz,
                        jstring user_profile_directory_path,
                        jobject dictionary_buffer,
                        jobject connection_data_buffer) {
  // Keep the global references of the buffers.
  g_dictionary_buffer = env->NewGlobalRef(dictionary_buffer);
  g_connection_data_buffer = env->NewGlobalRef(connection_data_buffer);

  jboolean is_copy = JNI_FALSE;
  const char *utf8_user_profile_directory_path =
      env->GetStringUTFChars(user_profile_directory_path, &is_copy);

  JavaVM *vm = NULL;
  env->GetJavaVM(&vm);

  Initialize(
      vm, utf8_user_profile_directory_path,
      env->GetDirectBufferAddress(dictionary_buffer),
      env->GetDirectBufferCapacity(dictionary_buffer),
      env->GetDirectBufferAddress(connection_data_buffer),
      env->GetDirectBufferCapacity(connection_data_buffer));
  if (is_copy) {
    env->ReleaseStringUTFChars(user_profile_directory_path,
                               utf8_user_profile_directory_path);
  }
}

jstring JNICALL getVersion(JNIEnv *env) {
  return env->NewStringUTF(Version::GetMozcVersion().c_str());
}

}  // namespace
}  // namespace jni
}  // namespace mozc

extern "C" {
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
  JNIEnv *env = mozc::AndroidUtil::GetEnv(vm);
  if (!env) {
    // Fatal error. No way to recover.
     return JNI_EVERSION;
  }
  const JNINativeMethod methods[] = {
      {"evalCommand",
       "([B)[B",
       reinterpret_cast<void*>(&mozc::jni::evalCommand)},
      {"onPostLoad",
       "(Ljava/lang/String;Ljava/nio/Buffer;Ljava/nio/Buffer;)V",
       reinterpret_cast<void*>(&mozc::jni::onPostLoad)},
      {"getVersion",
       "()Ljava/lang/String;",
       reinterpret_cast<void*>(&mozc::jni::getVersion)},
  };
  jclass clazz = env->FindClass(
      "org/mozc/android/inputmethod/japanese/session/MozcJNI");
  if (env->RegisterNatives(clazz, methods, arraysize(methods))) {
    // Fatal error. No way to recover.
     return JNI_EVERSION;
  }

  mozc::Logging::InitLogStream("libmozc.so");
  return JNI_VERSION_1_6;
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
#ifdef MOZC_ENABLE_HTTP_CLIENT
  mozc::jni::JavaHttpClientProxy::SetJavaVM(NULL);
#endif  // MOZC_ENABLE_HTTP_CLIENT

  // Delete global references.
  JNIEnv *env = mozc::AndroidUtil::GetEnv(vm);
  if (env) {
    env->DeleteGlobalRef(mozc::jni::g_connection_data_buffer);
    env->DeleteGlobalRef(mozc::jni::g_dictionary_buffer);
  }
}
}  // extern "C"
