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

#include <ndn-cxx/util/segment-fetcher.hpp>

namespace ndn {
namespace tools {
namespace autoconfig {

static const Name LOCALHOP_HUB_DISCOVERY_PREFIX = "/localhop/ndn-autoconf/hub";

MulticastDiscovery::MulticastDiscovery(Face& face, KeyChain& keyChain,
                                       const NextStageCallback& nextStageOnFailure)
  : Base(face, keyChain, nextStageOnFailure)
  , m_nRequestedRegs(0)
  , m_nFinishedRegs(0)
{
}

void
MulticastDiscovery::start()
{
  std::cerr << "Trying multicast discovery..." << std::endl;

  util::SegmentFetcher::fetch(
    m_face, Interest("/localhost/nfd/faces/list"),
    m_validator,
    [this] (const ConstBufferPtr& data) { registerHubDiscoveryPrefix(data); },
    [this] (uint32_t code, const std::string& msg) { m_nextStageOnFailure(msg); });
}

void
MulticastDiscovery::registerHubDiscoveryPrefix(const ConstBufferPtr& buffer)
{
  std::vector<uint64_t> multicastFaces;

  size_t offset = 0;
  while (offset < buffer->size()) {
    bool isOk = false;
    Block block;
    std::tie(isOk, block) = Block::fromBuffer(buffer, offset);
    if (!isOk) {
      std::cerr << "ERROR: cannot decode FaceStatus TLV" << std::endl;
      break;
    }

    offset += block.size();

    ndn::nfd::FaceStatus faceStatus(block);

    FaceUri uri(faceStatus.getRemoteUri());
    if (uri.getScheme() == "udp4") {
      namespace ip = boost::asio::ip;
      boost::system::error_code ec;
      ip::address address = ip::address::from_string(uri.getHost(), ec);

      if (!ec && address.is_multicast()) {
        multicastFaces.push_back(faceStatus.getFaceId());
      }
      else
        continue;
    }
  }

  if (multicastFaces.empty()) {
    m_nextStageOnFailure("No multicast faces available, skipping multicast discovery stage");
  }
  else {
    ControlParameters parameters;
    parameters
      .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
      .setCost(1)
      .setExpirationPeriod(time::seconds(30));

    m_nRequestedRegs = multicastFaces.size();
    m_nFinishedRegs = 0;

    for (const auto& face : multicastFaces) {
      parameters.setFaceId(face);
      m_controller.start<ndn::nfd::RibRegisterCommand>(
        parameters,
        bind(&MulticastDiscovery::onRegisterSuccess, this),
        bind(&MulticastDiscovery::onRegisterFailure, this, _1));
    }
  }
}

void
MulticastDiscovery::onRegisterSuccess()
{
  ++m_nFinishedRegs;

  if (m_nRequestedRegs == m_nFinishedRegs) {
    MulticastDiscovery::setStrategy();
  }
}

void
MulticastDiscovery::onRegisterFailure(const ControlResponse& response)
{
  std::cerr << "ERROR: " << response.getText() << " (code: " << response.getCode() << ")" << std::endl;
  --m_nRequestedRegs;

  if (m_nRequestedRegs == m_nFinishedRegs) {
    if (m_nRequestedRegs > 0) {
      MulticastDiscovery::setStrategy();
    }
    else {
      m_nextStageOnFailure("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
                           " for all multicast faces, skipping multicast discovery stage");
    }
  }
}

void
MulticastDiscovery::setStrategy()
{
  ControlParameters parameters;
  parameters
    .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
    .setStrategy("/localhost/nfd/strategy/multicast");

  m_controller.start<ndn::nfd::StrategyChoiceSetCommand>(
    parameters,
    bind(&MulticastDiscovery::requestHubData, this),
    bind(&MulticastDiscovery::onSetStrategyFailure, this, _1));
}

void
MulticastDiscovery::onSetStrategyFailure(const ControlResponse& response)
{
  m_nextStageOnFailure("Failed to set multicast strategy for " +
                       LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + response.getText() + "). "
                       "Skipping multicast discovery stage");
}

void
MulticastDiscovery::requestHubData()
{
  Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
  interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
  interest.setMustBeFresh(true);

  m_face.expressInterest(interest,
                         bind(&MulticastDiscovery::onSuccess, this, _2),
                         bind(m_nextStageOnFailure, "Timeout"));
}

void
MulticastDiscovery::onSuccess(Data& data)
{
  const Block& content = data.getContent();
  content.parse();

  // Get Uri
  Block::element_const_iterator blockValue = content.find(tlv::nfd::Uri);
  if (blockValue == content.elements_end()) {
    m_nextStageOnFailure("Incorrect reply to multicast discovery stage");
    return;
  }
  std::string hubUri(reinterpret_cast<const char*>(blockValue->value()), blockValue->value_size());
  this->connectToHub(hubUri);
}

} // namespace autoconfig
} // namespace tools
} // namespace ndn
