/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2017,  The University of Memphis,
 *                           Regents of the University of California,
 *                           Arizona Board of Regents.
 *
 * This file is part of NLSR (Named-data Link State Routing).
 * See AUTHORS.md for complete list of NLSR authors and contributors.
 *
 * NLSR 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.
 *
 * NLSR 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
 * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#ifndef NLSR_SYNC_LOGIC_HANDLER_HPP
#define NLSR_SYNC_LOGIC_HANDLER_HPP

#include "test-access-control.hpp"
#include "signals.hpp"

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/util/signal.hpp>
#include <ChronoSync/socket.hpp>
#include <boost/throw_exception.hpp>

class InterestManager;

namespace nlsr {

class ConfParameter;

/*! \brief NLSR-to-ChronoSync interaction point
 *
 * This class serves as the abstraction for the syncing portion of
 * NLSR and its components. NLSR has no particular reliance on
 * ChronoSync, except that the NLSR source would need to be modified
 * for use with other sync protocols.
 *
 */
class SyncLogicHandler
{
public:
  using IsLsaNew =
    std::function<bool(const ndn::Name&, const std::string& lsaType, const uint64_t&)>;

  class Error : public std::runtime_error
  {
  public:
    explicit
    Error(const std::string& what)
      : std::runtime_error(what)
    {
    }
  };

  SyncLogicHandler(ndn::Face& face, const IsLsaNew& isLsaNew, ConfParameter& conf);

  /*! \brief Hook function to call whenever sync detects new data.
   *
   * This function packages the sync information into discrete updates
   * and passes those off to another function, processUpdateFromSync.
   * \sa processUpdateFromSync
   *
   * \param v A container with the new information sync has received
   */
  void
  onChronoSyncUpdate(const std::vector<chronosync::MissingDataInfo>& v);

  /*! \brief Instruct ChronoSync to publish an update.
   *
   * This function instructs sync to push an update into the network,
   * based on whatever the state of the sequencing manager is when
   * this is called. Since each ChronoSync instance maintains its own
   * PIT, doing this satisfies those interests so that other routers
   * know a sync update is available.
   * \sa publishSyncUpdate
   */
  void
  publishRoutingUpdate(const ndn::Name& type, const uint64_t& seqNo);

  /*! \brief Create and configure a socket to enable ChronoSync for this NLSR.
   *
   * In a typical situation this only needs to be called once, when NLSR starts.
   * \param syncPrefix The sync prefix you want this ChronoSync to use
   * \sa Nlsr::initialize
   */
  void
  createSyncSocket(const ndn::Name& syncPrefix);

PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  /*! \brief Simple function to glue Name components together
   */
  void
  buildUpdatePrefix();

private:
  /*! \brief Determine which kind of LSA was updated and fetch it.
   *
   * Checks that the received update is not from us, which can happen,
   * and then inspects the update to determine which kind of LSA the
   * update is for. Finally, it expresses interest for the correct LSA
   * type.
   * \throws SyncUpdate::Error If the sync update doesn't look like a sync LSA update.
   */
  void
  processUpdateFromSync(const ndn::Name& originRouter,
                        const ndn::Name& updateName, const uint64_t& seqNo);

  /*! \brief Instruct ChronoSync, via the sync socket, to publish an update.
   *
   * Each ChronoSync instance maintains its own PIT for sync
   * updates. This function creates a data that satisfies that update,
   * so that the interested routers will know new data is available.
   */
  void
  publishSyncUpdate(const ndn::Name& updatePrefix, uint64_t seqNo);

public:
  std::unique_ptr<OnNewLsa> onNewLsa;

private:
  ndn::Face& m_syncFace;
  std::shared_ptr<chronosync::Socket> m_syncSocket;
  ndn::Name m_syncPrefix;
  IsLsaNew m_isLsaNew;
  const ConfParameter& m_confParam;

PUBLIC_WITH_TESTS_ELSE_PRIVATE:
  ndn::Name m_nameLsaUserPrefix;
  ndn::Name m_adjLsaUserPrefix;
  ndn::Name m_coorLsaUserPrefix;

private:
  static const std::string NLSR_COMPONENT;
  static const std::string LSA_COMPONENT;

};

} // namespace nlsr

#endif // NLSR_SYNC_LOGIC_HANDLER_HPP
