/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
#ifndef EXTENSIONS_JVMLOADER_H
#define EXTENSIONS_JVMLOADER_H

#include <string>
#include <map>
#include <vector>
#include <sstream>
#include <iterator>
#include <algorithm>
#include "JavaClass.h"
#include "JavaServicer.h"
#include "../JavaException.h"
#include "core/Core.h"
#include <jni.h>
#ifndef WIN32
#include <dlfcn.h>
#endif
#include "Core.h"

namespace org {
namespace apache {
namespace nifi {
namespace minifi {
namespace jni {

/**
 * Purpose and Justification: Provides a mapping function for jfields.
 * Note that jFieldIDs aren't local references, so we don't need to worry
 * about keeping them around. Thus this class provides us a caching mechanism.
 */
class FieldMapping {
 public:
  jfieldID getField(const std::string &clazz, const std::string &fnArg) {
    std::lock_guard<std::mutex> guard(mutex_);
    auto group = map_.find(clazz);
    if (group != map_.end()) {
      auto match = group->second.find(fnArg);
      if (match != group->second.end()) {
        return match->second;
      }
    }
    return nullptr;
  }

  void putField(const std::string &clazz, const std::string &fnArg, jfieldID field) {
    std::lock_guard<std::mutex> guard(mutex_);
    map_[clazz].insert(std::make_pair(fnArg, field));
  }

 private:
  std::mutex mutex_;
  std::map<std::string, std::map<std::string, jfieldID>> map_;
};

typedef jint (*registerNatives_t)(JNIEnv* env, jclass clazz);

jfieldID getPtrField(JNIEnv *env, jobject obj);

template<typename T>
T *getPtr(JNIEnv *env, jobject obj);

template<typename T>
void setPtr(JNIEnv *env, jobject obj, T *t);

/**
 * Purpose and Justification: Provides a singleton reference to a JVM.
 *
 * Since JVMs are singular in reference ( meaning that there cannot be more than one
 * at any given time ), we need to create a singleton access pattern.
 *
 */
class JVMLoader {
 public:

  bool initialized() {
    return initialized_;
  }

  /**
   * Attach the current thread
   * @return JNIEnv reference.
   */
  JNIEnv *attach(const std::string &name = "") {
    JNIEnv* jenv;
    jint ret = jvm_->GetEnv((void**) &jenv, JNI_VERSION_1_8);

    if (ret == JNI_EDETACHED) {
      ret = jvm_->AttachCurrentThread((void**) &jenv, NULL);
      if (ret != JNI_OK || jenv == NULL) {
        throw std::runtime_error("Could not find class");
      }
    }

    return jenv;
  }

  void detach(){
    jvm_->DetachCurrentThread();
  }

  /**
   * Returns a reference to an instantiated class loader
   * @return class loader.
   */
  jobject getClassLoader() {
    return gClassLoader;
  }

  /**
   * Removes a class reference
   * @param name class name
   */
  void remove_class(const std::string &name) {
    std::lock_guard<std::mutex> lock(internal_mutex_);
    auto finder = objects_.find(name);
    if (finder != objects_.end()) {
      auto oldClzz = finder->second;
      JavaClass clazz(oldClzz);
      attach(name)->DeleteGlobalRef(clazz.getReference());
    }
    objects_.erase(name);
  }

  /**
   * Loads a class, creating a global reference to the jclass
   * @param class name.
   * @return JavaClass
   */
  JavaClass load_class(const std::string &clazz_name, JNIEnv *lenv = nullptr) {
    // names should come with package/package/name, so we must normalize the name

    JNIEnv *env = lenv;

    // when we do the lookup here we will be using a boostrap CL so we'll need
    // to ensure class names are not in their canonical form. Since we want to
    // support both we will do the transition from . to / and later on from
    // / to . to normalize. Forcing all classes that enter this method
    // to be a certain way isn't very defensible.
    std::string name = clazz_name;
    name = utils::StringUtils::replaceAll(name, ".", "/");

    if (env == nullptr) {
      env = attach(name);
    }

    std::lock_guard<std::mutex> lock(internal_mutex_);
    auto finder = objects_.find(name);
    if (finder != objects_.end()) {
      auto oldClzz = finder->second;
      JavaClass clazz(oldClzz);
      return clazz;
    }

    std::string modifiedName = name;
    modifiedName = utils::StringUtils::replaceAll(modifiedName, "/", ".");

    auto jstringclass = env->NewStringUTF(modifiedName.c_str());

    auto preclass = env->CallObjectMethod(gClassLoader, gFindClassMethod, jstringclass);

    minifi::jni::ThrowIf(env);

    auto obj = (jclass) env->NewGlobalRef(preclass);

    minifi::jni::ThrowIf(env);

    auto clazzobj = static_cast<jclass>(obj);

    JavaClass clazz(name, clazzobj, env);
    objects_.insert(std::make_pair(name, clazz));
    return clazz;
  }

  JavaClass getObjectClass(const std::string &name, jobject jobj) {
    auto env = attach();
    auto jcls = (jclass) env->NewGlobalRef(env->GetObjectClass(jobj));
    return JavaClass(name, jcls, env);
  }

  static JVMLoader *getInstance() {
    static JVMLoader jvm;
    return &jvm;
  }

  JNIEnv *getEnv() {
    return env_;
  }

  /**
   * Returns an instance to the JVMLoader
   * @param pathVector vector of paths
   * @param otherOptions jvm options.
   */
  static JVMLoader *getInstance(const std::vector<std::string> &pathVector, const std::vector<std::string> &otherOptions = std::vector<std::string>()) {
    JVMLoader *jvm = getInstance();
    if (!jvm->initialized()) {
      std::stringstream str;
      std::vector<std::string> options;
      for (const auto &path : pathVector) {
        if (str.str().length() > 0) {
#ifdef WIN32
          str << ";" << path;
#else
          str << ":" << path;
#endif
        } else
          str << path;
      }
      options.insert(options.end(), otherOptions.begin(), otherOptions.end());
      std::string classpath = "-Djava.class.path=" + str.str();
      options.push_back(classpath);
      jvm->initialize(options);
    }
    return jvm;
  }

  template<typename T>
  void setReference(jobject obj, T *t) {
    setPtr(env_, obj, t);
  }

  template<typename T>
  void setReference(jobject obj, JNIEnv *env, T *t) {
    setPtr(env, obj, t);
  }

  template<typename T>
  T *getReference(JNIEnv *env, jobject obj) {
    return getPtr<T>(env, obj);
  }

  /**
   * Get the pointer field to the
   * This expects nativePtr to exist. I've always used nativePtr because I know others use it across
   * stack overflow. It's a common field, so the hope is that we can potentially access any class
   * in which the native pointer is stored in nativePtr.
   */
  static jfieldID getPtrField(const std::string &className, JNIEnv *env, jobject obj) {
    static std::string fn = "nativePtr", args = "J", lookup = "nativePtrJ";
    auto field = getClassMapping().getField(className, lookup);
    if (field != nullptr) {
      return field;
    }

    jclass c = env->GetObjectClass(obj);
    return env->GetFieldID(c, "nativePtr", "J");
  }

  template<typename T>
  static T *getPtr(JNIEnv *env, jobject obj) {
    jlong handle = env->GetLongField(obj, getPtrField(minifi::core::getClassName<T>(), env, obj));
    return reinterpret_cast<T *>(handle);
  }

  template<typename T>
  static void setPtr(JNIEnv *env, jobject obj, T *t) {
    jlong handle = reinterpret_cast<jlong>(t);
    env->SetLongField(obj, getPtrField(minifi::core::getClassName<T>(), env, obj), handle);
  }

  void setBaseServicer(std::shared_ptr<JavaServicer> servicer) {
    java_servicer_ = servicer;
  }

  std::shared_ptr<JavaServicer> getBaseServicer() const {
    std::lock_guard<std::mutex> lock(internal_mutex_);
    return java_servicer_;
  }

  template<typename T>
  static void putClassMapping(JNIEnv *env, JavaClass &clazz, const std::string &fieldStr, const std::string &arg) {
    auto classref = clazz.getReference();
    auto name = minifi::core::getClassName<T>();
    auto field = env->GetFieldID(classref, fieldStr.c_str(), arg.c_str());
    auto fieldName = fieldStr + arg;
    getClassMapping().putField(name, fieldName, field);

  }

 protected:

  static FieldMapping &getClassMapping() {
    static FieldMapping map;
    return map;
  }

  mutable std::mutex internal_mutex_;

#ifdef WIN32

// base_object doesn't have a handle
  std::map< HMODULE, std::string > resource_mapping_;

  std::string error_str_;
  std::string current_error_;

  void store_error() {
    auto error = GetLastError();

    if (error == 0) {
      error_str_ = "";
      return;
    }

    LPSTR messageBuffer = nullptr;
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    current_error_ = std::string(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);
  }

  void *dlsym(void *handle, const char *name)
  {
    FARPROC symbol;
    HMODULE hModule;

    symbol = GetProcAddress((HMODULE)handle, name);

    if (symbol == nullptr) {
      store_error();

      for (auto hndl : resource_mapping_)
      {
        symbol = GetProcAddress((HMODULE)hndl.first, name);
        if (symbol != nullptr) {
          break;
        }
      }
    }

#ifdef _MSC_VER
#pragma warning( suppress: 4054 )
#endif
    return (void*)symbol;
  }

  const char *dlerror(void)
  {
    std::lock_guard<std::mutex> lock(internal_mutex_);

    error_str_ = current_error_;

    current_error_ = "";

    return error_str_.c_str();
  }

  void *dlopen(const char *file, int mode) {
    std::lock_guard<std::mutex> lock(internal_mutex_);
    HMODULE object;
    char * current_error = NULL;
    uint32_t uMode = SetErrorMode(SEM_FAILCRITICALERRORS);
    if (nullptr == file)
    {
      HMODULE allModules[1024];
      HANDLE current_process_id = GetCurrentProcess();
      DWORD cbNeeded;
      object = GetModuleHandle(NULL);

      if (!object)
      store_error();
      if (EnumProcessModules(current_process_id, allModules,
              sizeof(allModules), &cbNeeded) != 0)
      {

        for (uint32_t i = 0; i < cbNeeded / sizeof(HMODULE); i++)
        {
          TCHAR szModName[MAX_PATH];

          // Get the full path to the module's file.
          resource_mapping_.insert(std::make_pair(allModules[i], "minifi-system"));
        }
      }
    }
    else
    {
      char lpFileName[MAX_PATH];
      int i;

      for (i = 0; i < sizeof(lpFileName) - 1; i++)
      {
        if (!file[i])
        break;
        else if (file[i] == '/')
        lpFileName[i] = '\\';
        else
        lpFileName[i] = file[i];
      }
      lpFileName[i] = '\0';
      object = LoadLibraryEx(lpFileName, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
      if (!object)
      store_error();
      else if ((mode & RTLD_GLOBAL))
      resource_mapping_.insert(std::make_pair(object, lpFileName));
    }

    /* Return to previous state of the error-mode bit flags. */
    SetErrorMode(uMode);

    return (void *)object;

  }

  int dlclose(void *handle)
  {
    std::lock_guard<std::mutex> lock(internal_mutex_);

    HMODULE object = (HMODULE)handle;
    BOOL ret;

    current_error_ = "";
    ret = FreeLibrary(object);

    resource_mapping_.erase(object);

    ret = !ret;

    return (int)ret;
  }

#endif

  inline jclass find_class_global(JNIEnv* env, const char *name) {
    jclass c = env->FindClass(name);
    jclass c_global = (jclass) env->NewGlobalRef(c);
    if (!c) {
      std::stringstream ss;
      ss << "Could not find " << name;
      throw std::runtime_error(ss.str());
    }
    return c_global;
  }

  void initialize(const std::vector<std::string> &opts) {
    string_options_ = opts;
    java_options_ = new JavaVMOption[opts.size()];
    int i = 0;
    for (const auto &opt : string_options_) {
      java_options_[i++].optionString = const_cast<char*>(opt.c_str());
    }

    JavaVMInitArgs vm_args;
    // rely on 1.8 and above
    vm_args.version = JNI_VERSION_1_8;
    vm_args.nOptions = opts.size();
    vm_args.options = java_options_;
    // if we see an unrecognized option fail.
    vm_args.ignoreUnrecognized = JNI_FALSE;
    // load and initialize a Java VM, return a JNI interface
    // pointer in env
    JNI_CreateJavaVM(&jvm_, (void**) &env_, &vm_args);
    // we're actually using a known class to locate the class loader and provide it
    // to referentially perform lookups.
    auto randomClass = find_class_global(env_, "org/apache/nifi/processor/ProcessContext");
    jclass classClass = env_->GetObjectClass(randomClass);
    auto classLoaderClass = find_class_global(env_, "java/lang/ClassLoader");
    auto getClassLoaderMethod = env_->GetMethodID(classClass, "getClassLoader", "()Ljava/lang/ClassLoader;");
    auto refclazz = env_->CallObjectMethod(randomClass, getClassLoaderMethod);
    minifi::jni::ThrowIf(env_);
    gClassLoader = env_->NewGlobalRef(refclazz);
    gFindClassMethod = env_->GetMethodID(classLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    minifi::jni::ThrowIf(env_);
    initialized_ = true;
  }

 private:

  std::atomic<bool> initialized_;

  std::map<std::string, JavaClass> objects_;

  std::vector<std::string> string_options_;

  JavaVMOption* java_options_;

  JavaVM *jvm_;
  JNIEnv *env_;

  jobject gClassLoader;
  jmethodID gFindClassMethod;

  std::shared_ptr<JavaServicer> java_servicer_;

  JVMLoader()
      : java_options_(nullptr),
        jvm_(nullptr),
        env_(nullptr),
        java_servicer_(nullptr),
        gFindClassMethod(nullptr),
        gClassLoader(nullptr) {
    initialized_ = false;
  }

  ~JVMLoader() {
    if (java_options_) {
      delete[] java_options_;
    }
  }
};

} /* namespace jni */
} /* namespace minifi */
} /* namespace nifi */
} /* namespace apache */
} /* namespace org */

#endif /* EXTENSIONS_JVMLOADER_H */
