/* -*- 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 "nrd.hpp"

namespace ndn {
namespace nrd {

const Name Nrd::COMMAND_PREFIX = "/localhost/nrd";

const size_t Nrd::COMMAND_UNSIGNED_NCOMPS =
  Nrd::COMMAND_PREFIX.size() +
  1 + // verb
  1;  // verb options

const size_t Nrd::COMMAND_SIGNED_NCOMPS =
  Nrd::COMMAND_UNSIGNED_NCOMPS +
  4; // (timestamp, nonce, signed info tlv, signature tlv)

const Nrd::VerbAndProcessor Nrd::COMMAND_VERBS[] =
  {
    VerbAndProcessor(
                     Name::Component("register"),
                     &Nrd::insertEntry
                     ),

    VerbAndProcessor(
                     Name::Component("unregister"),
                     &Nrd::deleteEntry
                     ),
  };

void
setInterestFilterFailed(const Name& name, const std::string& msg) 
{
  std::cerr << "Error in setting interest filter (" << name << "): " << msg << std::endl;
}

Nrd::Nrd()
  : m_nfdController(new nfd::Controller(m_face)),
    m_verbDispatch(COMMAND_VERBS,
                   COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
{
  m_face.setController(m_nfdController);
  m_face.setInterestFilter("/localhost/nrd",
                           bind(&Nrd::onRibRequest, this, _2),
                           bind(&setInterestFilterFailed, _1, _2));
}

void
Nrd::sendResponse(const Name& name,
                  const nfd::ControlResponse& response)
{
  const Block& encodedControl = response.wireEncode();

  Data responseData(name);
  responseData.setContent(encodedControl);

  m_keyChain.sign(responseData);
  m_face.put(responseData);
}

void
Nrd::sendResponse(const Name& name,
                  uint32_t code,
                  const std::string& text)
{
  nfd::ControlResponse response(code, text);
  sendResponse(name, response);
}

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

  if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
      commandNComps < COMMAND_SIGNED_NCOMPS)
    {
      std::cerr << "Error: Signature required" << std::endl;
      sendResponse(command, 401, "Signature required");
      return;
    }
  else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
           !COMMAND_PREFIX.isPrefixOf(command))
    {
      std::cerr << "Error: Malformed Command" << std::endl;
      sendResponse(command, 400, "Malformed command");
      return;
    }

  const Name::Component& verb = command.get(COMMAND_PREFIX.size());
  VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);

  if (verbProcessor != m_verbDispatch.end())
    {
      PrefixRegOptions options;
      if (!extractOptions(request, options))
        {
          sendResponse(command, 400, "Malformed command");
          return;
        }

      /// \todo authorize command
      if (false)
        {
          sendResponse(request.getName(), 403, "Unauthorized command");
          return;
        }

      // \todo add proper log support
      std::cout << "Received options (name, faceid, cost): " << options.getName() << 
                   ", " << options.getFaceId() << ", "  << options.getCost() << std::endl;

      nfd::ControlResponse response;
      (verbProcessor->second)(this, request, options);
    }
  else
    {
      sendResponse(request.getName(), 501, "Unsupported command");
    }
}

bool
Nrd::extractOptions(const Interest& request,
                    PrefixRegOptions& extractedOptions)
{
  const Name& command = request.getName();
  const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;

  try
    {
      Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
      extractedOptions.wireDecode(rawOptions);
    }
  catch (const ndn::Tlv::Error& e)
    {
      return false;
    }

  if (extractedOptions.getFaceId() == 0)
    {
      std::cout <<"IncomingFaceId: " << request.getIncomingFaceId() << std::endl;
      extractedOptions.setFaceId(request.getIncomingFaceId());
    }
  return true;
}

void
Nrd::onCommandError(const std::string& error, 
                    const Interest& request, 
                    const PrefixRegOptions& options)
{
  nfd::ControlResponse response;
  
  response.setCode(400);
  response.setText(error);
  
  std::cout << "Error: " << error << std::endl;
  sendResponse(request.getName(), response);
  m_managedRib.erase(options);
}

void
Nrd::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
{
  nfd::ControlResponse response;
  
  response.setCode(200);
  response.setText("Success");
  response.setBody(options.wireEncode());
 
  std::cout << "Success: Name unregistered (" << 
                options.getName() << ", " << 
                options.getFaceId() << ")" << std::endl;
  sendResponse(request.getName(), response);
  m_managedRib.erase(options);
}

void
Nrd::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
{
  nfd::ControlResponse response;
  
  response.setCode(200);
  response.setText("Success");
  response.setBody(options.wireEncode());
  
  std::cout << "Success: Name registered (" << options.getName() << ", " << 
                                               options.getFaceId() << ")" << std::endl;
  sendResponse(request.getName(), response);
}


void
Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
{
  // For right now, just pass the options to fib as it is,
  // without processing flags. Later options will be first added to
  // Rib tree, then nrd will generate fib updates based on flags and then
  // will add next hops one by one..
  m_managedRib.insert(options);
  m_nfdController->fibAddNextHop(options.getName(), options.getFaceId(),
                                 options.getCost(),
                                 bind(&Nrd::onRegSuccess, this, request, options),
                                 bind(&Nrd::onCommandError, this, _1, request, options));
}


void
Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
{
  m_nfdController->fibRemoveNextHop(options.getName(),
                                    options.getFaceId(),
                                    bind(&Nrd::onUnRegSuccess, this, request, options),
                                    bind(&Nrd::onCommandError, this, _1, request, options));
}


void
Nrd::listen()
{
  std::cout << "NRD started: listening for incoming interests" << std::endl;
  m_face.processEvents();
}


void
Nrd::onControlHeaderSuccess()
{
  std::cout << "Local control header enabled" << std::endl;
}


void
Nrd::onControlHeaderError()
{
  std::cout << "Error: couldn't enable local control header" << std::endl;
  m_face.shutdown();
}


void
Nrd::enableLocalControlHeader()
{
  Name enable("/localhost/nfd/control-header/in-faceid/enable");
  Interest enableCommand(enable);
 
  m_keyChain.sign(enableCommand);
  m_face.expressInterest(enableCommand,
                         ndn::bind(&Nrd::onControlHeaderSuccess, this),
                         ndn::bind(&Nrd::onControlHeaderError, this));
}

} // namespace nrd
} // namespace ndn
