/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2011-2015  Regents of the University of California.
 *
 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
 * contributors.
 *
 * ndnSIM 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.
 *
 * ndnSIM 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
 * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "ndn-l3-protocol.hpp"

#include "ns3/packet.h"
#include "ns3/node.h"
#include "ns3/log.h"
#include "ns3/callback.h"
#include "ns3/uinteger.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/object-vector.h"
#include "ns3/pointer.h"
#include "ns3/simulator.h"

#include "ndn-net-device-link-service.hpp"

#include "../helper/ndn-stack-helper.hpp"
#include "cs/ndn-content-store.hpp"

#include <boost/property_tree/info_parser.hpp>

#include "ns3/ndnSIM/NFD/daemon/fw/forwarder.hpp"
#include "ns3/ndnSIM/NFD/daemon/face/internal-face.hpp"
#include "ns3/ndnSIM/NFD/daemon/face/internal-transport.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/fib-manager.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/face-manager.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/strategy-choice-manager.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/forwarder-status-manager.hpp"
// #include "ns3/ndnSIM/NFD/daemon/mgmt/general-config-section.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/tables-config-section.hpp"
#include "ns3/ndnSIM/NFD/daemon/mgmt/command-validator.hpp"

#include "ns3/ndnSIM/NFD/rib/rib-manager.hpp"

#include "ns3/ndnSIM/NFD/daemon/face/null-face.hpp"
#include "ns3/ndnSIM/NFD/daemon/face/internal-face.hpp"

#include "ns3/ndnSIM/NFD/core/config-file.hpp"

#include <ndn-cxx/mgmt/dispatcher.hpp>

NS_LOG_COMPONENT_DEFINE("ndn.L3Protocol");

namespace ns3 {
namespace ndn {

const uint16_t L3Protocol::ETHERNET_FRAME_TYPE = 0x7777;
const uint16_t L3Protocol::IP_STACK_PORT = 9695;

NS_OBJECT_ENSURE_REGISTERED(L3Protocol);

TypeId
L3Protocol::GetTypeId(void)
{
  static TypeId tid =
    TypeId("ns3::ndn::L3Protocol")
      .SetGroupName("ndn")
      .SetParent<Object>()
      .AddConstructor<L3Protocol>()

      .AddTraceSource("OutInterests", "OutInterests",
                      MakeTraceSourceAccessor(&L3Protocol::m_outInterests),
                      "ns3::ndn::L3Protocol::InterestTraceCallback")
      .AddTraceSource("InInterests", "InInterests",
                      MakeTraceSourceAccessor(&L3Protocol::m_inInterests),
                      "ns3::ndn::L3Protocol::InterestTraceCallback")

      ////////////////////////////////////////////////////////////////////

      .AddTraceSource("OutData", "OutData", MakeTraceSourceAccessor(&L3Protocol::m_outData),
                      "ns3::ndn::L3Protocol::DataTraceCallback")
      .AddTraceSource("InData", "InData", MakeTraceSourceAccessor(&L3Protocol::m_inData),
                      "ns3::ndn::L3Protocol::DataTraceCallback")

      ////////////////////////////////////////////////////////////////////

      .AddTraceSource("SatisfiedInterests", "SatisfiedInterests",
                      MakeTraceSourceAccessor(&L3Protocol::m_satisfiedInterests),
                      "ns3::ndn::L3Protocol::SatisfiedInterestsCallback")
      .AddTraceSource("TimedOutInterests", "TimedOutInterests",
                      MakeTraceSourceAccessor(&L3Protocol::m_timedOutInterests),
                      "ns3::ndn::L3Protocol::TimedOutInterestsCallback")
    ;
  return tid;
}

class L3Protocol::Impl {
private:
  Impl()
  {
    // Do not modify initial config file. Use helpers to set specific NFD parameters
    std::string initialConfig =
      "general\n"
      "{\n"
      "}\n"
      "\n"
      "tables\n"
      "{\n"
      "  cs_max_packets 100\n"
      "\n"
      "  strategy_choice\n"
      "  {\n"
      "    /               /localhost/nfd/strategy/best-route\n"
      "    /localhost      /localhost/nfd/strategy/multicast\n"
      "    /localhost/nfd  /localhost/nfd/strategy/best-route\n"
      "    /ndn/multicast  /localhost/nfd/strategy/multicast\n"
      "  }\n"
      "}\n"
      "\n"
      // "face_system\n"
      // "{\n"
      // "}\n"
      "\n"
      "authorizations\n"
      "{\n"
      "  authorize\n"
      "  {\n"
      "    certfile any\n"
      "    privileges\n"
      "    {\n"
      "      faces\n"
      "      fib\n"
      "      strategy-choice\n"
      "    }\n"
      "  }\n"
      "}\n"
      "\n"
      "rib\n"
      "{\n"
      "  localhost_security\n"
      "  {\n"
      "    trust-anchor\n"
      "    {\n"
      "      type any\n"
      "    }\n"
      "  }\n"
      "}\n"
      "\n";

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

  friend class L3Protocol;

  std::shared_ptr<nfd::Forwarder> m_forwarder;

  std::shared_ptr<nfd::Face> m_internalFace;
  std::shared_ptr<::ndn::Face> m_internalClientFace;
  std::unique_ptr<nfd::CommandValidator> m_validator;

  std::shared_ptr<nfd::Face> m_internalRibFace;
  std::shared_ptr<::ndn::Face> m_internalRibClientFace;

  std::unique_ptr<::ndn::mgmt::Dispatcher> m_dispatcher;
  std::shared_ptr<nfd::FibManager> m_fibManager;
  std::shared_ptr<nfd::FaceManager> m_faceManager;
  std::shared_ptr<nfd::StrategyChoiceManager> m_strategyChoiceManager;
  std::shared_ptr<nfd::ForwarderStatusManager> m_forwarderStatusManager;
  std::shared_ptr<nfd::rib::RibManager> m_ribManager;

  nfd::ConfigSection m_config;

  Ptr<ContentStore> m_csFromNdnSim;
};

L3Protocol::L3Protocol()
  : m_impl(new Impl())
{
  NS_LOG_FUNCTION(this);
}

L3Protocol::~L3Protocol()
{
  NS_LOG_FUNCTION(this);
}

void
L3Protocol::initialize()
{
  m_impl->m_forwarder = make_shared<nfd::Forwarder>();

  initializeManagement();

  nfd::FaceTable& faceTable = m_impl->m_forwarder->getFaceTable();
  faceTable.addReserved(nfd::face::makeNullFace(), nfd::face::FACEID_NULL);
  faceTable.addReserved(nfd::face::makeNullFace(FaceUri("contentstore://")), nfd::face::FACEID_CONTENT_STORE);

  if (!this->getConfig().get<bool>("ndnSIM.disable_rib_manager", false)) {
    Simulator::ScheduleWithContext(m_node->GetId(), Seconds(0), &L3Protocol::initializeRibManager, this);
  }

  m_impl->m_forwarder->beforeSatisfyInterest.connect(std::ref(m_satisfiedInterests));
  m_impl->m_forwarder->beforeExpirePendingInterest.connect(std::ref(m_timedOutInterests));
}

class IgnoreSections
{
public:
  IgnoreSections(const std::vector<std::string>& ignored)
    : m_ignored(ignored)
  {
  }

  void
  operator()(const std::string& filename, const std::string& sectionName,
             const nfd::ConfigSection& section, bool isDryRun)

  {
    if (std::find(m_ignored.begin(), m_ignored.end(), sectionName) == m_ignored.end()) {
      nfd::ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
    }
  }
private:
  std::vector<std::string> m_ignored;
};

void
L3Protocol::injectInterest(const Interest& interest)
{
  m_impl->m_internalFace->sendInterest(interest);
}

void
L3Protocol::initializeManagement()
{
  auto& forwarder = m_impl->m_forwarder;
  using namespace nfd;

  std::tie(m_impl->m_internalFace, m_impl->m_internalClientFace) = face::makeInternalFace(StackHelper::getKeyChain());
  forwarder->getFaceTable().addReserved(m_impl->m_internalFace, face::FACEID_INTERNAL_FACE);
  m_impl->m_dispatcher.reset(new ::ndn::mgmt::Dispatcher(*m_impl->m_internalClientFace, StackHelper::getKeyChain()));

  m_impl->m_validator.reset(new CommandValidator());

  m_impl->m_fibManager.reset(new FibManager(forwarder->getFib(),
                                            bind(&Forwarder::getFace, forwarder.get(), _1),
                                            *m_impl->m_dispatcher,
                                            *m_impl->m_validator));

  // Cannot be disabled for now
  // if (!this->getConfig().get<bool>("ndnSIM.disable_face_manager", false)) {
  m_impl->m_faceManager.reset(new FaceManager(forwarder->getFaceTable(),
                                              *m_impl->m_dispatcher,
                                              *m_impl->m_validator));
  // }
  // else {
  //   this->getConfig().get_child("authorizations").get_child("authorize").get_child("privileges").erase("faces");
  // }

  if (!this->getConfig().get<bool>("ndnSIM.disable_strategy_choice_manager", false)) {
    m_impl->m_strategyChoiceManager.reset(new StrategyChoiceManager(forwarder->getStrategyChoice(),
                                                                    *m_impl->m_dispatcher,
                                                                    *m_impl->m_validator));
  }
  else {
    this->getConfig().get_child("authorizations").get_child("authorize").get_child("privileges").erase("strategy-choice");
  }

  if (!this->getConfig().get<bool>("ndnSIM.disable_forwarder_status_manager", false)) {
    m_impl->m_forwarderStatusManager.reset(new ForwarderStatusManager(*forwarder, *m_impl->m_dispatcher));
  }

  ConfigFile config(&ConfigFile::ignoreUnknownSection);

  TablesConfigSection tablesConfig(forwarder->getCs(),
                                   forwarder->getPit(),
                                   forwarder->getFib(),
                                   forwarder->getStrategyChoice(),
                                   forwarder->getMeasurements(),
                                   forwarder->getNetworkRegionTable());
  tablesConfig.setConfigFile(config);

  m_impl->m_validator->setConfigFile(config);

  // if (!this->getConfig().get<bool>("ndnSIM.disable_face_manager", false)) {
  m_impl->m_faceManager->setConfigFile(config);
  // }

  // apply config
  config.parse(m_impl->m_config, false, "ndnSIM.conf");

  tablesConfig.ensureTablesAreConfigured();

  // add FIB entry for NFD Management Protocol
  Name topPrefix("/localhost/nfd");
  auto entry = forwarder->getFib().insert(topPrefix).first;
  entry->addNextHop(m_impl->m_internalFace, 0);
  m_impl->m_dispatcher->addTopPrefix(topPrefix, false);
}

void
L3Protocol::initializeRibManager()
{
  using namespace nfd;

  std::tie(m_impl->m_internalRibFace, m_impl->m_internalRibClientFace) = face::makeInternalFace(StackHelper::getKeyChain());
  m_impl->m_forwarder->getFaceTable().add(m_impl->m_internalRibFace);
  m_impl->m_ribManager = make_shared<rib::RibManager>(*(m_impl->m_internalRibClientFace),
                                                      StackHelper::getKeyChain());

  ConfigFile config([] (const std::string& filename, const std::string& sectionName,
                        const ConfigSection& section, bool isDryRun) {
      // Ignore "log" and sections belonging to NFD,
      // but raise an error if we're missing a handler for a "rib" section.
      if (sectionName != "rib" || sectionName == "log") {
        // do nothing
      }
      else {
        // missing RIB section
        ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
      }
    });

  m_impl->m_ribManager->setConfigFile(config);

  // apply config
  config.parse(m_impl->m_config, false, "ndnSIM.conf");

  m_impl->m_ribManager->registerWithNfd();

  m_impl->m_ribManager->enableLocalControlHeader();
}

shared_ptr<nfd::Forwarder>
L3Protocol::getForwarder()
{
  return m_impl->m_forwarder;
}

shared_ptr<nfd::FibManager>
L3Protocol::getFibManager()
{
  return m_impl->m_fibManager;
}

shared_ptr<nfd::StrategyChoiceManager>
L3Protocol::getStrategyChoiceManager()
{
  return m_impl->m_strategyChoiceManager;
}

nfd::ConfigSection&
L3Protocol::getConfig()
{
  return m_impl->m_config;
}

/*
 * This method is called by AddAgregate and completes the aggregation
 * by setting the node in the ndn stack
 */
void
L3Protocol::NotifyNewAggregate()
{
  if (m_node == nullptr) {
    m_node = GetObject<Node>();
    if (m_node != nullptr) {
      initialize();

      NS_ASSERT(m_impl->m_forwarder != nullptr);
      m_impl->m_csFromNdnSim = GetObject<ContentStore>();
      if (m_impl->m_csFromNdnSim != nullptr) {
        m_impl->m_forwarder->setCsFromNdnSim(m_impl->m_csFromNdnSim);
      }
    }
  }

  Object::NotifyNewAggregate();
}

void
L3Protocol::DoDispose(void)
{
  NS_LOG_FUNCTION(this);

  // MUST HAPPEN BEFORE Simulator IS DESTROYED
  m_impl.reset();

  nfd::scheduler::getGlobalScheduler().cancelAllEvents();

  m_node = 0;

  Object::DoDispose();
}

nfd::FaceId
L3Protocol::addFace(shared_ptr<Face> face)
{
  NS_LOG_FUNCTION(this << face.get());

  m_impl->m_forwarder->addFace(face);

  std::weak_ptr<Face> weakFace = face;

  // // Connect Signals to TraceSource
  face->afterReceiveInterest.connect([this, weakFace](const Interest& interest) {
      shared_ptr<Face> face = weakFace.lock();
      if (face != nullptr) {
        this->m_inInterests(interest, *face);
      }
    });

  face->afterReceiveData.connect([this, weakFace](const Data& data) {
      shared_ptr<Face> face = weakFace.lock();
      if (face != nullptr) {
        this->m_inData(data, *face);
      }
    });

  // TODO: Discover why these signal were removed and fix it

  // face->afterSendInterest.connect
  //   ([this, weakFace](const Interest& interest) { this->m_outInterests(interest, *face); });

  // face->afterSendData.connect([this, weakFace](const Data& data) { this->m_outData(data, *face); });

  return face->getId();
}

shared_ptr<Face>
L3Protocol::getFaceById(nfd::FaceId id) const
{
  return m_impl->m_forwarder->getFaceTable().get(id);
}

shared_ptr<Face>
L3Protocol::getFaceByNetDevice(Ptr<NetDevice> netDevice) const
{
  for (const auto& i : m_impl->m_forwarder->getFaceTable()) {
    auto linkService = dynamic_cast<NetDeviceLinkService*>(i->getLinkService());
    if (linkService == nullptr)
      continue;

    if (linkService->GetNetDevice() == netDevice)
      return i;
  }
  return nullptr;
}

Ptr<L3Protocol>
L3Protocol::getL3Protocol(Ptr<Object> node)
{
  Ptr<L3Protocol> retval = node->GetObject<L3Protocol>();
  NS_ASSERT_MSG(retval != nullptr, "L3Protocol is not aggregated on this object");
  return retval;
}

} // namespace ndn
} // namespace ns3
