/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  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/>.
 */

/** \file
 *  \brief allows testing forwarding in a network topology
 */

#ifndef NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP
#define NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/transport/transport.hpp>
#include "face/lp-face-wrapper.hpp"
#include "fw/strategy.hpp"
#include "tests/test-common.hpp"

namespace nfd {
namespace fw {
namespace tests {

using namespace nfd::tests;

/** \brief abstracts a Transport used in TopologyTester
 */
class TopologyTransportBase
{
public:
  /** \brief causes the transport to receive a link-layer packet
   */
  virtual void
  receiveFromTopology(const Block& packet) = 0;

  signal::Signal<TopologyTransportBase, Block> afterSend;

protected:
  DECLARE_SIGNAL_EMIT(afterSend)
};

/** \brief implements a forwarder-side Transport used in TopologyTester
 */
class TopologyForwarderTransport : public face::Transport, public TopologyTransportBase
{
public:
  TopologyForwarderTransport(const FaceUri& localUri, const FaceUri& remoteUri,
                             ndn::nfd::FaceScope scope, ndn::nfd::LinkType linkType);

  virtual void
  receiveFromTopology(const Block& packet) DECL_OVERRIDE;

protected:
  virtual void
  doClose() DECL_OVERRIDE
  {
  }

private:
  virtual void
  doSend(Packet&& packet) DECL_OVERRIDE;
};

/** \brief implements a client-side Transport used in TopologyTester
 */
class TopologyClientTransport : public ndn::Transport, public TopologyTransportBase
{
public:
  virtual void
  receiveFromTopology(const Block& packet) DECL_OVERRIDE;

  virtual void
  close() DECL_OVERRIDE
  {
  }

  virtual void
  pause() DECL_OVERRIDE
  {
  }

  virtual void
  resume() DECL_OVERRIDE
  {
  }

  virtual void
  send(const Block& wire) DECL_OVERRIDE;

  virtual void
  send(const Block& header, const Block& payload) DECL_OVERRIDE;
};

/** \brief identifies a node (forwarder) in the topology
 */
typedef size_t TopologyNode;

/** \brief represents a network or local-app link
 */
class TopologyLinkBase : noncopyable
{
public:
  TopologyLinkBase();

  /** \brief fail the link, cause packets to be dropped silently
   */
  void
  fail()
  {
    m_isUp = false;
  }

  /** \brief recover the link from a failure
   */
  void
  recover()
  {
    m_isUp = true;
  }

protected:
  /** \brief attach a Transport onto this link
   */
  void
  attachTransport(TopologyNode i, TopologyTransportBase* transport);

private:
  void
  transmit(TopologyNode i, const Block& packet);

  virtual void
  scheduleReceive(TopologyTransportBase* recipient, const Block& packet) = 0;

protected:
  bool m_isUp;
  std::unordered_map<TopologyNode, TopologyTransportBase*> m_transports;
};

/** \brief represents a network link in the topology which connects two or more nodes
 */
class TopologyLink : public TopologyLinkBase
{
public:
  explicit
  TopologyLink(const time::nanoseconds& delay);

  void
  addFace(TopologyNode i, shared_ptr<face::LpFaceWrapper> face);

  /** \return a face of forwarder \p i which is attached to this link
   */
  Face&
  getFace(TopologyNode i)
  {
    return *m_faces.at(i);
  }

private:
  virtual void
  scheduleReceive(TopologyTransportBase* recipient, const Block& packet) DECL_OVERRIDE;

private:
  time::nanoseconds m_delay;
  std::unordered_map<TopologyNode, shared_ptr<face::LpFaceWrapper>> m_faces;
};

/** \brief represents a link to a local application
 */
class TopologyAppLink : public TopologyLinkBase
{
public:
  explicit
  TopologyAppLink(shared_ptr<face::LpFaceWrapper> face);

  /** \return face on forwarder side
   */
  Face&
  getForwarderFace()
  {
    return *m_face;
  }

  /** \return face on application side
   */
  ndn::Face&
  getClientFace()
  {
    return *m_client;
  }

private:
  virtual void
  scheduleReceive(TopologyTransportBase* recipient, const Block& packet) DECL_OVERRIDE;

private:
  shared_ptr<face::LpFaceWrapper> m_face;
  shared_ptr<ndn::Face> m_client;
};

/** \brief builds a topology for forwarding tests
 */
class TopologyTester : noncopyable
{
public:
  /** \brief creates a forwarder
   *  \return index of new forwarder
   */
  TopologyNode
  addForwarder(const std::string& label);

  /** \return forwarder instance \p i
   */
  Forwarder&
  getForwarder(TopologyNode i)
  {
    return *m_forwarders.at(i);
  }

  /** \brief sets strategy on forwarder \p i
   *  \tparam the strategy type
   *  \note Test scenario can also access StrategyChoice table directly.
   */
  template<typename S>
  void
  setStrategy(TopologyNode i, Name prefix = Name("ndn:/"))
  {
    Forwarder& forwarder = this->getForwarder(i);
    StrategyChoice& strategyChoice = forwarder.getStrategyChoice();
    shared_ptr<S> strategy = make_shared<S>(ref(forwarder));
    strategyChoice.install(strategy);
    strategyChoice.insert(prefix, strategy->getName());
  }

  /** \brief makes a link that interconnects two or more forwarders
   *
   *  A face is created on each of \p forwarders .
   *  When a packet is sent onto one of the faces on this link,
   *  this packet will be received by all other faces on this link after \p delay .
   */
  shared_ptr<TopologyLink>
  addLink(const std::string& label, const time::nanoseconds& delay,
          std::initializer_list<TopologyNode> forwarders,
          bool forceMultiAccessFace = false);

  /** \brief makes a link to local application
   */
  shared_ptr<TopologyAppLink>
  addAppFace(const std::string& label, TopologyNode i);

  /** \brief makes a link to local application, and register a prefix
   */
  shared_ptr<TopologyAppLink>
  addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost = 0);

  /** \brief registers a prefix on a forwarder face
   */
  void
  registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost = 0);

  /** \brief creates a producer application that answers every Interest with Data of same Name
   */
  void
  addEchoProducer(ndn::Face& face, const Name& prefix = "/");

  /** \brief creates a consumer application that sends \p n Interests under \p prefix
   *         at \p interval fixed rate.
   */
  void
  addIntervalConsumer(ndn::Face& face, const Name& prefix,
                      const time::nanoseconds& interval, size_t n);

private:
  std::vector<unique_ptr<Forwarder>> m_forwarders;
  std::vector<std::string> m_forwarderLabels;
  std::vector<shared_ptr<TopologyLink>> m_links;
  std::vector<shared_ptr<TopologyAppLink>> m_appLinks;
};

} // namespace tests
} // namespace fw
} // namespace nfd

#endif // NFD_TESTS_NFD_FW_TOPOLOGY_TESTER_HPP
