/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (C) 2014 Named Data Networking Project
 * See COPYING for copyright and distribution information.
 */

#include "fib-manager.hpp"

#include "table/fib.hpp"
#include "fw/forwarder.hpp"
#include "mgmt/internal-face.hpp"
#include "mgmt/app-face.hpp"

#include <ndn-cpp-dev/management/fib-management-options.hpp>
#include <ndn-cpp-dev/encoding/tlv.hpp>


namespace nfd {

NFD_LOG_INIT("FibManager");

const Name FibManager::FIB_MANAGER_COMMAND_PREFIX = "/localhost/nfd/fib";

const size_t FibManager::FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS =
  FibManager::FIB_MANAGER_COMMAND_PREFIX.size() +
  1 + // verb
  1;  // verb options

const size_t FibManager::FIB_MANAGER_COMMAND_SIGNED_NCOMPS =
  FibManager::FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS +
  0; // No signed Interest support in mock, otherwise 3 (timestamp, signed info tlv, signature tlv)

const FibManager::VerbAndProcessor FibManager::FIB_MANAGER_COMMAND_VERBS[] =
  {
    VerbAndProcessor(
                     "insert",
                     &FibManager::insertEntry
                     ),

    VerbAndProcessor(
                     "delete",
                     &FibManager::deleteEntry
                     ),

    VerbAndProcessor(
                     "add-nexthop",
                     &FibManager::addNextHop
                     ),



    VerbAndProcessor(
                     "remove-nexthop",
                     &FibManager::removeNextHop
                     ),

    // Unsupported
    // VerbAndProcessor(
    //                  "strategy",
    //                  &FibManager::strategy
    //                  )

  };

FibManager::FibManager(Fib& fib,
                       function<shared_ptr<Face>(FaceId)> getFace,
                       shared_ptr<AppFace> face)
  : ManagerBase(face),
    m_managedFib(fib),
    m_getFace(getFace),
    m_verbDispatch(FIB_MANAGER_COMMAND_VERBS,
                   FIB_MANAGER_COMMAND_VERBS +
                   (sizeof(FIB_MANAGER_COMMAND_VERBS) / sizeof(VerbAndProcessor)))
{
  face->setInterestFilter("/localhost/nfd/fib",
                          bind(&FibManager::onFibRequest, this, _2));
}

void
FibManager::onFibRequest(const Interest& request)
{
  const Name& command = request.getName();
  const size_t commandNComps = command.size();

  if (FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
      commandNComps < FIB_MANAGER_COMMAND_SIGNED_NCOMPS)
    {
      NFD_LOG_INFO("command result: unsigned verb: " << command);
      sendResponse(command, 401, "Signature required");

      return;
    }
  else if (commandNComps < FIB_MANAGER_COMMAND_SIGNED_NCOMPS ||
      !FIB_MANAGER_COMMAND_PREFIX.isPrefixOf(command))
    {
      NFD_LOG_INFO("command result: malformed");
      sendResponse(command, 400, "Malformed command");
      return;
    }

  const Name::Component& verb = command.get(FIB_MANAGER_COMMAND_PREFIX.size());

  VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find (verb);
  if (verbProcessor != m_verbDispatch.end())
    {
      ndn::FibManagementOptions options;
      if (!extractOptions(request, options))
        {
          sendResponse(command, 400, "Malformed command");
          return;
        }

      /// \todo authorize command
      if (false)
        {
          NFD_LOG_INFO("command result: unauthorized verb: " << command);
          sendResponse(request.getName(), 403, "Unauthorized command");
          return;
        }

      NFD_LOG_INFO("command result: processing verb: " << verb);

      ndn::ControlResponse response;
      (verbProcessor->second)(this, options, response);

      sendResponse(command, response);
    }
  else
    {
      NFD_LOG_INFO("command result: unsupported verb: " << verb);
      sendResponse(request.getName(), 501, "Unsupported command");
    }

}

bool
FibManager::extractOptions(const Interest& request,
                           ndn::FibManagementOptions& extractedOptions)
{
  const Name& command = request.getName();
  const size_t optionCompIndex =
    FIB_MANAGER_COMMAND_PREFIX.size() + 1;

  const ndn::Buffer& optionBuffer =
    request.getName()[optionCompIndex].getValue();
  shared_ptr<const ndn::Buffer> tmpOptionBuffer(make_shared<ndn::Buffer>(optionBuffer));

  try
    {
      Block rawOptions(tmpOptionBuffer);
      extractedOptions.wireDecode(rawOptions);
    }
  catch (const ndn::Tlv::Error& e)
    {
      NFD_LOG_INFO("Bad command option parse: " << command);
      return false;
    }
  NFD_LOG_DEBUG("Options parsed OK");
  return true;
}

void
FibManager::insertEntry(const ndn::FibManagementOptions& options,
                        ndn::ControlResponse& response)
{
  NFD_LOG_DEBUG("insert prefix: " << options.getName());
  NFD_LOG_INFO("insert result: OK"
               << " prefix: " << options.getName());
  std::pair<shared_ptr<fib::Entry>, bool> insertResult = m_managedFib.insert(options.getName());
  setResponse(response, 200, "OK");
}

void
FibManager::deleteEntry(const ndn::FibManagementOptions& options,
                        ndn::ControlResponse& response)
{
  NFD_LOG_DEBUG("delete prefix: " << options.getName());
  NFD_LOG_INFO("delete result: OK"
               << " prefix: " << options.getName());

  m_managedFib.remove(options.getName());
  setResponse(response, 200, "OK");
}

static inline bool
nextHopEqPredicate(const fib::NextHop& target, const fib::NextHop& hop)
{
  return target.getFace()->getId() == hop.getFace()->getId();
}

void
FibManager::addNextHop(const ndn::FibManagementOptions& options,
                          ndn::ControlResponse& response)
{
  NFD_LOG_DEBUG("add-nexthop prefix: " << options.getName()
                << " faceid: " << options.getFaceId()
                << " cost: " << options.getCost());

  shared_ptr<Face> nextHopFace = m_getFace(options.getFaceId());
  if (static_cast<bool>(nextHopFace))
    {
      shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(options.getName());
      if (static_cast<bool>(entry))
        {
          entry->addNextHop(nextHopFace, options.getCost());

          NFD_LOG_INFO("add-nexthop result: OK"
                       << " prefix:" << options.getName()
                       << " faceid: " << options.getFaceId()
                       << " cost: " << options.getCost());
          setResponse(response, 200, "OK");
        }
      else
        {
          NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-prefix: " << options.getName());
          setResponse(response, 404, "Prefix not found");
        }
    }
  else
    {
      NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << options.getFaceId());
      setResponse(response, 404, "Face not found");
    }
}

void
FibManager::removeNextHop(const ndn::FibManagementOptions& options,
                             ndn::ControlResponse &response)
{
  NFD_LOG_DEBUG("remove-nexthop prefix: " << options.getName()
                << " faceid: " << options.getFaceId());

  shared_ptr<Face> faceToRemove = m_getFace(options.getFaceId());
  if (static_cast<bool>(faceToRemove))
    {
      shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(options.getName());
      if (static_cast<bool>(entry))
        {
          entry->removeNextHop(faceToRemove);
          NFD_LOG_INFO("remove-nexthop result: OK prefix: " << options.getName()
                       << " faceid: " << options.getFaceId());

          setResponse(response, 200, "OK");
        }
      else
        {
          NFD_LOG_INFO("remove-nexthop result: FAIL reason: unknown-prefix: "
                       << options.getName());
          setResponse(response, 404, "Prefix not found");
        }
    }
  else
    {
      NFD_LOG_INFO("remove-nexthop result: FAIL reason: unknown-faceid: "
                   << options.getFaceId());
      setResponse(response, 404, "Face not found");
    }
}

void
FibManager::strategy(const ndn::FibManagementOptions& options, ndn::ControlResponse& response)
{

}

// void
// FibManager::onConfig(ConfigFile::Node section, bool isDryRun)
// {

// }

} // namespace nfd
