/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California,
 *                      Arizona Board of Regents,
 *                      Colorado State University,
 *                      University Pierre & Marie Curie, Sorbonne University,
 *                      Washington University in St. Louis,
 *                      Beijing Institute of Technology,
 *                      The University of Memphis
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD 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 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, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "remote-registrator.hpp"
#include "core/logger.hpp"
#include "core/scheduler.hpp"

namespace nfd {
namespace rib {

NFD_LOG_INIT("RemoteRegistrator");

using ndn::nfd::ControlParameters;
using ndn::nfd::CommandOptions;


const Name RemoteRegistrator::RM_LOCAL_PREFIX = "/localhost";
const Name RemoteRegistrator::RM_HUB_PREFIX = "/localhop/nfd";
const name::Component RemoteRegistrator::RM_IGNORE_COMMPONENT("rib");

RemoteRegistrator::RemoteRegistrator(ndn::nfd::Controller& controller,
                                     ndn::KeyChain& keyChain,
                                     Rib& rib)
  : m_nfdController(controller)
  , m_keyChain(keyChain)
  , m_rib(rib)
  , m_refreshInterval(time::seconds(25))
  , m_hasConnectedHub(false)
  , m_nRetries(0)
{
}

RemoteRegistrator::~RemoteRegistrator()
{
  // cancel all periodically refresh events.
  for (auto&& entry : m_regEntries)
    {
      scheduler::cancel(entry.second);
    }
}

void
RemoteRegistrator::loadConfig(const ConfigSection& configSection)
{
  size_t cost = 15, timeout = 10000;
  size_t retry = 0;
  size_t interval = 0;
  const size_t intervalDef = 25, intervalMax = 600;

  NFD_LOG_INFO("Load remote_register section in rib section");
  for (auto&& i : configSection)
    {
      if (i.first == "cost")
        {
          cost = i.second.get_value<size_t>();
        }
      else if (i.first == "timeout")
        {
          timeout = i.second.get_value<size_t>();
        }
      else if (i.first == "retry")
        {
          retry = i.second.get_value<size_t>();
        }
      else if (i.first == "refresh_interval")
        {
          interval = i.second.get_value<size_t>();
        }
      else
        {
          throw ConfigFile::Error("Unrecognized option \"" + i.first +
                                  "\" in \"remote-registrator\" section");
        }
    }

   m_controlParameters
     .setCost(cost)
     .setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT)// set origin to client.
     .setFaceId(0);// the remote hub will take the input face as the faceId.

   m_commandOptions
     .setPrefix(RM_HUB_PREFIX)
     .setTimeout(time::milliseconds(timeout));

   m_nRetries = retry;

   if (interval == 0)
     {
       interval = intervalDef;
     }

   interval = std::min(interval, intervalMax);

   m_refreshInterval = time::seconds(interval);
}

void
RemoteRegistrator::registerPrefix(const Name& prefix)
{
  if (RM_LOCAL_PREFIX.isPrefixOf(prefix))
    {
      NFD_LOG_INFO("local registration only for " << prefix);
      return;
    }

  bool isHubPrefix = prefix == RM_HUB_PREFIX;

  if (isHubPrefix)
    {
      NFD_LOG_INFO("this is a prefix registered by some hub: " << prefix);

      m_hasConnectedHub = true;

      redoRegistration();
      return;
    }

  if (!m_hasConnectedHub)
    {
      NFD_LOG_INFO("no hub connected when registering " << prefix);
      return;
    }

  std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);

  if (0 == identity.second)
    {
      NFD_LOG_INFO("no proper identity found for registering " << prefix);
      return;
    }

  Name prefixForRegistration;
  if (identity.first.size() == identity.second)
    {
      prefixForRegistration = identity.first;
    }
  else
    {
      prefixForRegistration = identity.first.getPrefix(-1);
    }

  if (m_regEntries.find(prefixForRegistration) != m_regEntries.end())
    {
      NFD_LOG_INFO("registration already in process for " << prefix);
      return;
    }

  // make copies of m_controlParameters and m_commandOptions to
  // avoid unreasonable overwriting during concurrent registration
  // and unregistration.
  ControlParameters parameters = m_controlParameters;
  CommandOptions    options    = m_commandOptions;

  startRegistration(parameters.setName(prefixForRegistration),
                    options.setSigningIdentity(identity.first),
                    m_nRetries);
}

void
RemoteRegistrator::unregisterPrefix(const Name& prefix)
{
  if (prefix == RM_HUB_PREFIX)
    {
      NFD_LOG_INFO("disconnected to hub with prefix: " << prefix);

      // for phase 1: suppose there is at most one hub connected.
      // if the hub prefix has been unregistered locally, there may
      // be no connected hub.
      m_hasConnectedHub = false;

      clearRefreshEvents();
      return;
    }

  if (!m_hasConnectedHub)
    {
      NFD_LOG_INFO("no hub connected when unregistering " << prefix);
      return;
    }

  std::pair<Name, size_t> identity = findIdentityForRegistration(prefix);

  if (0 == identity.second)
    {
      NFD_LOG_INFO("no proper identity found for unregistering " << prefix);
      return;
    }

  Name prefixForRegistration;
  if (identity.first.size() == identity.second)
    {
      prefixForRegistration = identity.first;
    }
  else
    {
      prefixForRegistration = identity.first.getPrefix(-1);
    }

  RegisteredEntryIt iRegEntry = m_regEntries.find(prefixForRegistration);
  if (m_regEntries.end() == iRegEntry)
    {
      NFD_LOG_INFO("no existing entry found when unregistering " << prefix);
      return;
    }

  for (auto&& entry : m_rib)
    {
      if (prefixForRegistration.isPrefixOf(entry.first) &&
          findIdentityForRegistration(entry.first) == identity)
        {
          NFD_LOG_INFO("this identity should be kept for other rib entry: "
                       << entry.first);
          return;
        }
    }

  scheduler::cancel(iRegEntry->second);
  m_regEntries.erase(iRegEntry);

  // make copies of m_controlParameters and m_commandOptions to
  // avoid unreasonable overwriting during concurrent registration
  // and unregistration.
  ControlParameters parameters = m_controlParameters;
  CommandOptions    options    = m_commandOptions;

  startUnregistration(parameters.setName(prefixForRegistration).unsetCost(),
                      options.setSigningIdentity(identity.first),
                      m_nRetries);
}

std::pair<Name, size_t>
RemoteRegistrator::findIdentityForRegistration(const Name& prefix)
{
  std::pair<Name, size_t> candidateIdentity;
  std::vector<Name> identities;
  bool isPrefix = false;
  size_t maxLength = 0, curLength = 0;

  // get all identies from the key-cahin except the default one.
  m_keyChain.getAllIdentities(identities, false);

  // get the default identity.
  identities.push_back(m_keyChain.getDefaultIdentity());

  // longest prefix matching to all indenties.
  for (auto&& i : identities)
    {
      if (!i.empty() && RM_IGNORE_COMMPONENT == i.at(-1))
        {
          isPrefix = i.getPrefix(-1).isPrefixOf(prefix);
          curLength = i.size() - 1;
        }
      else
        {
          isPrefix = i.isPrefixOf(prefix);
          curLength = i.size();
        }

      if (isPrefix && curLength > maxLength)
        {
          candidateIdentity.first = i;
          maxLength = curLength;
        }
    }

  candidateIdentity.second = maxLength;

  return candidateIdentity;
}

void
RemoteRegistrator::startRegistration(const ControlParameters& parameters,
                                     const CommandOptions& options,
                                     int nRetries)
{
  NFD_LOG_INFO("start register " << parameters.getName());

  m_nfdController.start<ndn::nfd::RibRegisterCommand>(
     parameters,
     bind(&RemoteRegistrator::onRegSuccess,
          this, parameters, options),
     bind(&RemoteRegistrator::onRegFailure,
          this, _1, _2, parameters, options, nRetries),
     options);
}

void
RemoteRegistrator::startUnregistration(const ControlParameters& parameters,
                                       const CommandOptions& options,
                                       int nRetries)
{
  NFD_LOG_INFO("start unregister " << parameters.getName());

  m_nfdController.start<ndn::nfd::RibUnregisterCommand>(
     parameters,
     bind(&RemoteRegistrator::onUnregSuccess,
          this, parameters, options),
     bind(&RemoteRegistrator::onUnregFailure,
          this, _1, _2, parameters, options, nRetries),
     options);
}

void
RemoteRegistrator::onRegSuccess(const ControlParameters& parameters,
                                const CommandOptions& options)
{
  NFD_LOG_INFO("success to register " << parameters.getName());

  RegisteredEntryIt iRegEntry = m_regEntries.find(parameters.getName());

  if (m_regEntries.end() != iRegEntry)
    {
      NFD_LOG_DEBUG("Existing Entry: (" << iRegEntry->first
                                        << ", " << iRegEntry->second
                                        << ")");

      scheduler::cancel(iRegEntry->second);
      iRegEntry->second = scheduler::schedule(
                            m_refreshInterval,
                            bind(&RemoteRegistrator::startRegistration,
                                 this, parameters, options, m_nRetries));
    }
  else
    {
      NFD_LOG_DEBUG("New Entry");
      m_regEntries.insert(RegisteredEntry(
                              parameters.getName(),
                              scheduler::schedule(
                                m_refreshInterval,
                                bind(&RemoteRegistrator::startRegistration,
                                     this, parameters, options, m_nRetries))));
    }
}

void
RemoteRegistrator::onRegFailure(uint32_t code, const std::string& reason,
                                const ControlParameters& parameters,
                                const CommandOptions& options,
                                int nRetries)
{
  NFD_LOG_INFO("fail to unregister " << parameters.getName()
                                     << "\n\t reason:" << reason
                                     << "\n\t remain retries:" << nRetries);

  if (nRetries > 0)
    {
      startRegistration(parameters, options, nRetries - 1);
    }
}

void
RemoteRegistrator::onUnregSuccess(const ControlParameters& parameters,
                                  const CommandOptions& options)
{
  NFD_LOG_INFO("success to unregister " << parameters.getName());
}

void
RemoteRegistrator::onUnregFailure(uint32_t code, const std::string& reason,
                                  const ControlParameters& parameters,
                                  const CommandOptions& options,
                                  int nRetries)
{
  NFD_LOG_INFO("fail to unregister " << parameters.getName()
                                     << "\n\t reason:" << reason
                                     << "\n\t remain retries:" << nRetries);

  if (nRetries > 0)
    {
      startUnregistration(parameters, options, nRetries - 1);
    }
}

void
RemoteRegistrator::redoRegistration()
{
  NFD_LOG_INFO("redo " << m_regEntries.size()
                       << " registration when new Hub connection is built.");

  for (auto&& entry : m_regEntries)
    {
      // make copies to avoid unreasonable overwrite.
      ControlParameters parameters = m_controlParameters;
      CommandOptions    options    = m_commandOptions;
      startRegistration(parameters.setName(entry.first),
                        options.setSigningIdentity(entry.first),
                        m_nRetries);
    }
}

void
RemoteRegistrator::clearRefreshEvents()
{
  for (auto&& entry : m_regEntries)
    {
      scheduler::cancel(entry.second);
    }
}

} // namespace rib
} // namespace nfd
