/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2015-2019 Regents of the University of California
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon) Android.
 * See AUTHORS.md for complete list of NFD Android authors and contributors.
 *
 * NFD Android is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD Android, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "nfd-wrapper.hpp"

#include "daemon/nfd.hpp"
#include "rib/service.hpp"

#include "core/config-file.hpp"
#include "core/global-io.hpp"
#include "core/logger.hpp"
#include "core/privilege-helper.hpp"

#include <boost/property_tree/info_parser.hpp>
#include <boost/thread.hpp>
#include <mutex>
#include <ndn-cxx/util/logging.hpp>
#include <stdlib.h>

NFD_LOG_INIT(NfdWrapper);

namespace nfd {


// A little bit of cheating to make sure NFD can be properly restarted

namespace scheduler {
// defined in scheduler.cpp
void
resetGlobalScheduler();
} // namespace scheduler

void
resetGlobalIoService();

class Runner
{
public:
  Runner()
    : m_io(nullptr)
  {
    std::string initialConfig = R"CONF(
      log
      {
        default_level ALL
      }
      tables
      {
        cs_max_packets 100
        strategy_choice
        {
          /               /localhost/nfd/strategy/best-route
          /localhost      /localhost/nfd/strategy/multicast
          /localhost/nfd  /localhost/nfd/strategy/best-route
          /ndn/broadcast  /localhost/nfd/strategy/multicast
          /ndn/multicast  /localhost/nfd/strategy/multicast
          /sl             /localhost/nfd/strategy/self-learning
        }
      }
      face_system
      {
        tcp
        udp
        {
          mcast no
        }
        websocket
      }
      authorizations
      {
        authorize
        {
          certfile any
          privileges
          {
            faces
            fib
            cs
            strategy-choice
          }
        }
      }
      rib
      {
        localhost_security
        {
          trust-anchor
          {
            type any
          }
        }
        ; localhop_security
        ; {
        ;   trust-anchor
        ;   {
        ;     type any
        ;   }
        ; }
        auto_prefix_propagate
        {
          refresh_interval 300
        }
      }
    )CONF";

    std::istringstream input(initialConfig);
    boost::property_tree::read_info(input, m_config);

    m_nfd.reset(new Nfd(m_config, m_keyChain));
    m_ribService.reset(new rib::Service(m_config, m_keyChain));

    m_nfd->initialize();
  }

  void
  run()
  {
    {
      std::unique_lock<std::mutex> lock(m_pointerMutex);
      m_io = &getGlobalIoService();
    }

    setMainIoService(m_io);
    setRibIoService(m_io);

    m_io->run();
    m_io->reset();

    m_ribService.reset();
    m_nfd.reset();

    m_io = nullptr;
  }

  void
  stop()
  {
    std::unique_lock<std::mutex> lock(m_pointerMutex);

    if (m_io != nullptr) {
      m_io->stop();
    }
  }

private:
  std::mutex m_pointerMutex;
  boost::asio::io_service* m_io;
  ndn::KeyChain m_keyChain;
  unique_ptr<Nfd> m_nfd;
  unique_ptr<rib::Service> m_ribService;

  nfd::ConfigSection m_config;
};

static unique_ptr<Runner> g_runner;
static boost::thread g_thread;
static std::map<std::string, std::string> g_params;

} // namespace nfd


std::map<std::string, std::string>
getParams(JNIEnv* env, jobject jParams)
{
  std::map<std::string, std::string> params;

  jclass jcMap = env->GetObjectClass(jParams);
  jclass jcSet = env->FindClass("java/util/Set");
  jclass jcIterator = env->FindClass("java/util/Iterator");
  jclass jcMapEntry = env->FindClass("java/util/Map$Entry");

  jmethodID jcMapEntrySet      = env->GetMethodID(jcMap,      "entrySet", "()Ljava/util/Set;");
  jmethodID jcSetIterator      = env->GetMethodID(jcSet,      "iterator", "()Ljava/util/Iterator;");
  jmethodID jcIteratorHasNext  = env->GetMethodID(jcIterator, "hasNext",  "()Z");
  jmethodID jcIteratorNext     = env->GetMethodID(jcIterator, "next",     "()Ljava/lang/Object;");
  jmethodID jcMapEntryGetKey   = env->GetMethodID(jcMapEntry, "getKey",   "()Ljava/lang/Object;");
  jmethodID jcMapEntryGetValue = env->GetMethodID(jcMapEntry, "getValue", "()Ljava/lang/Object;");

  jobject jParamsEntrySet = env->CallObjectMethod(jParams, jcMapEntrySet);
  jobject jParamsIterator = env->CallObjectMethod(jParamsEntrySet, jcSetIterator);
  jboolean bHasNext = env->CallBooleanMethod(jParamsIterator, jcIteratorHasNext);
  while (bHasNext) {
    jobject entry = env->CallObjectMethod(jParamsIterator, jcIteratorNext);

    jstring jKey = (jstring)env->CallObjectMethod(entry, jcMapEntryGetKey);
    jstring jValue = (jstring)env->CallObjectMethod(entry, jcMapEntryGetValue);

    const char* cKey = env->GetStringUTFChars(jKey, nullptr);
    const char* cValue = env->GetStringUTFChars(jValue, nullptr);

    params.insert(std::make_pair(cKey, cValue));

    env->ReleaseStringUTFChars(jKey, cKey);
    env->ReleaseStringUTFChars(jValue, cValue);

    bHasNext = env->CallBooleanMethod(jParamsIterator, jcIteratorHasNext);
  }

  return params;
}


JNIEXPORT void JNICALL
Java_net_named_1data_nfd_service_NfdService_startNfd(JNIEnv* env, jclass, jobject jParams)
{
  if (nfd::g_runner.get() == nullptr) {
    nfd::g_params = getParams(env, jParams);

    // set/update HOME environment variable
    ::setenv("HOME", nfd::g_params["homePath"].c_str(), true);
    NFD_LOG_INFO("Use [" << nfd::g_params["homePath"] << "] as a security storage");

    nfd::g_thread = boost::thread([] {
        nfd::scheduler::resetGlobalScheduler();
        nfd::resetGlobalIoService();

        NFD_LOG_INFO("Starting NFD...");
        try {
          nfd::g_runner.reset(new nfd::Runner());
          nfd::g_runner->run();
        }
        catch (const std::exception& e) {
          NFD_LOG_FATAL(e.what());
        }
        catch (const nfd::PrivilegeHelper::Error& e) {
          NFD_LOG_FATAL("PrivilegeHelper: " << e.what());
        }
        catch (...) {
          NFD_LOG_FATAL("Unknown fatal error");
        }

        nfd::g_runner.reset();
        nfd::scheduler::resetGlobalScheduler();
        nfd::resetGlobalIoService();
        NFD_LOG_INFO("NFD stopped");
      });
  }
}

JNIEXPORT void JNICALL
Java_net_named_1data_nfd_service_NfdService_stopNfd(JNIEnv*, jclass)
{
  if (nfd::g_runner.get() != nullptr) {
    NFD_LOG_INFO("Stopping NFD...");
    nfd::g_runner->stop();
    // do not block anything
  }
}

JNIEXPORT jboolean JNICALL
Java_net_named_1data_nfd_service_NfdService_isNfdRunning(JNIEnv*, jclass)
{
  return nfd::g_runner.get() != nullptr;
}
