/* -*- 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-transport.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-authenticator.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("OutNack", "OutNack", MakeTraceSourceAccessor(&L3Protocol::m_outNack),
                      "ns3::ndn::L3Protocol::NackTraceCallback")
      .AddTraceSource("InNack", "InNack", MakeTraceSourceAccessor(&L3Protocol::m_inNack),
                      "ns3::ndn::L3Protocol::NackTraceCallback")

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

      .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::shared_ptr<nfd::CommandAuthenticator> m_authenticator;

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

  std::unique_ptr<::ndn::mgmt::Dispatcher> m_dispatcher;
  std::unique_ptr<::ndn::mgmt::Dispatcher> m_dispatcherRib;
  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;
  PolicyCreationCallback m_policy;
};

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::setCsReplacementPolicy(const PolicyCreationCallback& policy)
{
  m_impl->m_policy = policy;
}

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_authenticator = CommandAuthenticator::create();

  m_impl->m_fibManager.reset(new FibManager(forwarder->getFib(),
                                            forwarder->getFaceTable(),
                                            *m_impl->m_dispatcher,
                                            *m_impl->m_authenticator));

  // 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_authenticator));
  // }
  // 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_authenticator));
  }
  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);

  // if we use NFD's CS, we have to specify a replacement policy
  m_impl->m_csFromNdnSim = GetObject<ContentStore>();
  if (m_impl->m_csFromNdnSim == nullptr) {
    forwarder->getCs().setPolicy(m_impl->m_policy());
  }

  TablesConfigSection tablesConfig(*forwarder);
  tablesConfig.setConfigFile(config);

  m_impl->m_authenticator->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.ensureConfigured();

  // 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_dispatcherRib.reset(new ::ndn::mgmt::Dispatcher(*m_impl->m_internalRibClientFace, StackHelper::getKeyChain()));

  m_impl->m_ribManager = make_shared<rib::RibManager>(*(m_impl->m_dispatcherRib), *(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();
}

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);
      }
    });

  face->afterReceiveNack.connect([this, weakFace](const lp::Nack& nack) {
      shared_ptr<Face> face = weakFace.lock();
      if (face != nullptr) {
        this->m_inNack(nack, *face);
      }
    });

  auto tracingLink = face->getLinkService();
  NS_LOG_LOGIC("Adding trace sources for afterSendInterest and afterSendData");
  tracingLink->afterSendInterest.connect([this, weakFace](const Interest& interest) {
      shared_ptr<Face> face = weakFace.lock();
      if (face != nullptr) {
        this->m_outInterests(interest, *face);
      }
    });

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

  tracingLink->afterSendNack.connect([this, weakFace](const lp::Nack& nack) {
      shared_ptr<Face> face = weakFace.lock();
      if (face != nullptr) {
        this->m_outNack(nack, *face);
      }
    });

  return face->getId();
}

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

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

    if (transport->GetNetDevice() == netDevice)
      return i.shared_from_this();
  }
  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
