/* -*- 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/>.
 */

#include "topology-tester.hpp"
#include <ndn-cxx/encoding/encoding-buffer-fwd.hpp>
#include "face/generic-link-service.hpp"

namespace nfd {
namespace fw {
namespace tests {

using face::InternalTransportBase;
using face::InternalForwarderTransport;
using face::InternalClientTransport;
using face::GenericLinkService;

TopologyLink::TopologyLink(const time::nanoseconds& delay)
  : m_isUp(true)
  , m_delay(delay)
{
  BOOST_ASSERT(delay > time::nanoseconds::zero());
  // zero delay does not work on OSX
}

void
TopologyLink::addFace(TopologyNode i, shared_ptr<Face> face)
{
  this->attachTransport(i, dynamic_cast<InternalTransportBase*>(face->getTransport()));
  m_faces[i] = face;
}

void
TopologyLink::attachTransport(TopologyNode i, InternalTransportBase* transport)
{
  BOOST_ASSERT(transport != nullptr);
  BOOST_ASSERT(m_transports.count(i) == 0);

  m_transports[i] = transport;
  transport->afterSend.connect([this, i] (const Block& packet) { this->transmit(i, packet); });
}

void
TopologyLink::transmit(TopologyNode i, const Block& packet)
{
  if (!m_isUp) {
    return;
  }

  for (auto&& p : m_transports) {
    if (p.first == i) {
      continue;
    }

    InternalTransportBase* recipient = p.second;
    this->scheduleReceive(recipient, packet);
  }
}

void
TopologyLink::scheduleReceive(InternalTransportBase* recipient, const Block& packet)
{
  scheduler::schedule(m_delay, [packet, recipient] {
    recipient->receiveFromLink(packet);
  });
}

TopologyAppLink::TopologyAppLink(shared_ptr<Face> forwarderFace)
  : m_face(forwarderFace)
  , m_forwarderTransport(static_cast<InternalForwarderTransport*>(forwarderFace->getTransport()))
  , m_clientTransport(make_shared<InternalClientTransport>())
  , m_client(make_shared<ndn::Face>(m_clientTransport, getGlobalIoService()))
{
  this->recover();
}

void
TopologyAppLink::fail()
{
  m_clientTransport->connectToForwarder(nullptr);
}

void
TopologyAppLink::recover()
{
  m_clientTransport->connectToForwarder(m_forwarderTransport);
}

TopologyNode
TopologyTester::addForwarder(const std::string& label)
{
  size_t i = m_forwarders.size();
  m_forwarders.push_back(std::move(make_unique<Forwarder>()));
  m_forwarderLabels.push_back(label);
  BOOST_ASSERT(m_forwarders.size() == m_forwarderLabels.size());
  return i;
}

shared_ptr<TopologyLink>
TopologyTester::addLink(const std::string& label, const time::nanoseconds& delay,
                        std::initializer_list<TopologyNode> forwarders,
                        bool forceMultiAccessFace)
{
  auto link = make_shared<TopologyLink>(delay);
  FaceUri remoteUri("topology://link/" + label);
  ndn::nfd::LinkType linkType = (forceMultiAccessFace || forwarders.size() > 2) ?
                                ndn::nfd::LINK_TYPE_MULTI_ACCESS :
                                ndn::nfd::LINK_TYPE_POINT_TO_POINT;

  for (TopologyNode i : forwarders) {
    Forwarder& forwarder = this->getForwarder(i);
    FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/" + label);

    auto service = make_unique<GenericLinkService>();
    auto transport = make_unique<InternalForwarderTransport>(localUri, remoteUri,
                     ndn::nfd::FACE_SCOPE_NON_LOCAL, linkType);
    auto face = make_shared<Face>(std::move(service), std::move(transport));

    forwarder.addFace(face);
    link->addFace(i, face);
  }

  m_links.push_back(link); // keep a shared_ptr so callers don't have to
  return link;
}

shared_ptr<TopologyAppLink>
TopologyTester::addAppFace(const std::string& label, TopologyNode i)
{
  Forwarder& forwarder = this->getForwarder(i);
  FaceUri localUri("topology://" + m_forwarderLabels.at(i) + "/local/" + label);
  FaceUri remoteUri("topology://" + m_forwarderLabels.at(i) + "/app/" + label);

  auto service = make_unique<GenericLinkService>();
  auto transport = make_unique<InternalForwarderTransport>(localUri, remoteUri,
                   ndn::nfd::FACE_SCOPE_LOCAL, ndn::nfd::LINK_TYPE_POINT_TO_POINT);
  auto face = make_shared<Face>(std::move(service), std::move(transport));

  forwarder.addFace(face);

  auto al = make_shared<TopologyAppLink>(face);
  m_appLinks.push_back(al); // keep a shared_ptr so callers don't have to
  return al;
}

shared_ptr<TopologyAppLink>
TopologyTester::addAppFace(const std::string& label, TopologyNode i, const Name& prefix, uint64_t cost)
{
  shared_ptr<TopologyAppLink> al = this->addAppFace(label, i);
  this->registerPrefix(i, al->getForwarderFace(), prefix, cost);
  return al;
}

void
TopologyTester::registerPrefix(TopologyNode i, const Face& face, const Name& prefix, uint64_t cost)
{
  Forwarder& forwarder = this->getForwarder(i);
  Fib& fib = forwarder.getFib();
  shared_ptr<fib::Entry> fibEntry = fib.insert(prefix).first;
  fibEntry->addNextHop(const_cast<Face&>(face).shared_from_this(), cost);
}

void
TopologyTester::addEchoProducer(ndn::Face& face, const Name& prefix)
{
  face.setInterestFilter(prefix,
      [&face] (const ndn::InterestFilter&, const Interest& interest) {
        shared_ptr<Data> data = makeData(interest.getName());
        face.put(*data);
      });
}

void
TopologyTester::addIntervalConsumer(ndn::Face& face, const Name& prefix,
                                    const time::nanoseconds& interval, size_t n)
{
  Name name(prefix);
  name.appendTimestamp();
  shared_ptr<Interest> interest = makeInterest(name);
  face.expressInterest(*interest, bind([]{}));

  if (n > 1) {
    scheduler::schedule(interval, bind(&TopologyTester::addIntervalConsumer, this,
                                       ref(face), prefix, interval, n - 1));
  }
}

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