/* -*- 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 "version.hpp"

#include "core/face-uri.hpp"

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/management/nfd-controller.hpp>
#include <ndn-cxx/management/nfd-face-status.hpp>
#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/encoding/buffer-stream.hpp>

#include <boost/lexical_cast.hpp>

#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>

#ifdef __APPLE__
#include <arpa/nameser_compat.h>
#endif

namespace ndn {
namespace tools {

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

void
usage(const char* programName)
{
  std::cout << "Usage:\n" << programName  << " [-h] [-V]\n"
            << "   -h  - print usage and exit\n"
            << "   -V  - print version number and exit\n"
            << std::endl;
}

class NdnAutoconfig
{
public:
  union QueryAnswer
  {
    HEADER header;
    uint8_t buf[NS_PACKETSZ];
  };

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

  explicit
  NdnAutoconfig()
    : m_controller(m_face)
  {
  }

  void
  run()
  {
    m_face.processEvents();
  }

  void
  fetchSegments(const Data& data, const shared_ptr<OBufferStream>& buffer,
                void (NdnAutoconfig::*onDone)(const shared_ptr<OBufferStream>&))
  {
    buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
                  data.getContent().value_size());

    uint64_t currentSegment = data.getName().get(-1).toSegment();

    const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
    if (finalBlockId.empty() ||
        finalBlockId.toSegment() > currentSegment)
      {
        m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
                               bind(&NdnAutoconfig::fetchSegments, this, _2, buffer, onDone),
                               bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
      }
    else
      {
        return (this->*onDone)(buffer);
      }
  }

  void
  discoverHubStage1()
  {
    shared_ptr<OBufferStream> buffer = make_shared<OBufferStream>();

    Interest interest("/localhost/nfd/faces/list");
    interest.setChildSelector(1);
    interest.setMustBeFresh(true);

    m_face.expressInterest(interest,
                           bind(&NdnAutoconfig::fetchSegments, this, _2, buffer,
                                &NdnAutoconfig::discoverHubStage1_registerHubDiscoveryPrefix),
                           bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
  }

  void
  discoverHubStage1_registerHubDiscoveryPrefix(const shared_ptr<OBufferStream>& buffer)
  {
    ConstBufferPtr buf = buffer->buf();
    std::vector<uint64_t> multicastFaces;

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

        offset += block.size();

        nfd::FaceStatus faceStatus(block);

        ::nfd::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()) {
      discoverHubStage2("No multicast faces available, skipping stage 1");
    }
    else {
      shared_ptr<nfd::Controller> controller = make_shared<nfd::Controller>(ref(m_face));
      shared_ptr<std::pair<size_t, size_t> > nRegistrations =
        make_shared<std::pair<size_t, size_t> >(0, 0);

      nfd::ControlParameters parameters;
      parameters
        .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
        .setCost(1)
        .setExpirationPeriod(time::seconds(30));

      nRegistrations->first = multicastFaces.size();

      for (std::vector<uint64_t>::iterator i = multicastFaces.begin();
           i != multicastFaces.end(); ++i) {
        parameters.setFaceId(*i);

        controller->start<nfd::RibRegisterCommand>(parameters,
          bind(&NdnAutoconfig::discoverHubStage1_onRegisterSuccess,
               this, controller, nRegistrations),
          bind(&NdnAutoconfig::discoverHubStage1_onRegisterFailure,
               this, _1, _2, controller, nRegistrations));
      }
    }
  }

  void
  discoverHubStage1_onRegisterSuccess(const shared_ptr<nfd::Controller>& controller,
                                      const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
  {
    nRegistrations->second++;

    if (nRegistrations->first == nRegistrations->second) {
      discoverHubStage1_setStrategy(controller);
    }
  }

  void
  discoverHubStage1_onRegisterFailure(uint32_t code, const std::string& error,
                                      const shared_ptr<nfd::Controller>& controller,
                                      const shared_ptr<std::pair<size_t, size_t> >& nRegistrations)
  {
    std::cerr << "ERROR: " << error << " (code: " << code << ")" << std::endl;
    nRegistrations->first--;

    if (nRegistrations->first == nRegistrations->second) {
      if (nRegistrations->first > 0) {
        discoverHubStage1_setStrategy(controller);
      } else {
        discoverHubStage2("Failed to register " + LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() +
                          " for all multicast faces");
      }
    }
  }

  void
  discoverHubStage1_setStrategy(const shared_ptr<nfd::Controller>& controller)
  {
    nfd::ControlParameters parameters;
    parameters
      .setName(LOCALHOP_HUB_DISCOVERY_PREFIX)
      .setStrategy("/localhost/nfd/strategy/broadcast");

    controller->start<nfd::StrategyChoiceSetCommand>(parameters,
      bind(&NdnAutoconfig::discoverHubStage1_onSetStrategySuccess,
           this, controller),
      bind(&NdnAutoconfig::discoverHubStage1_onSetStrategyFailure,
           this, _2, controller));
  }

  void
  discoverHubStage1_onSetStrategySuccess(const shared_ptr<nfd::Controller>& controller)
  {
    discoverHubStage1_requestHubData();
  }

  void
  discoverHubStage1_onSetStrategyFailure(const std::string& error,
                                         const shared_ptr<nfd::Controller>& controller)
  {
    discoverHubStage2("Failed to set broadcast strategy for " +
                      LOCALHOP_HUB_DISCOVERY_PREFIX.toUri() + " namespace (" + error + ")");
  }

  // Start to look for a hub (NDN hub discovery first stage)
  void
  discoverHubStage1_requestHubData()
  {
    Interest interest(LOCALHOP_HUB_DISCOVERY_PREFIX);
    interest.setInterestLifetime(time::milliseconds(4000)); // 4 seconds
    interest.setMustBeFresh(true);

    std::cerr << "Stage 1: Trying multicast discovery..." << std::endl;
    m_face.expressInterest(interest,
                           bind(&NdnAutoconfig::onDiscoverHubStage1Success, this, _1, _2),
                           bind(&NdnAutoconfig::discoverHubStage2, this, "Timeout"));
  }

  // First stage OnData Callback
  void
  onDiscoverHubStage1Success(const Interest& interest, 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())
    {
      discoverHubStage2("Incorrect reply to stage1");
      return;
    }
    std::string faceMgmtUri(reinterpret_cast<const char*>(blockValue->value()),
                            blockValue->value_size());
    connectToHub(faceMgmtUri);
  }

  // First stage OnTimeout callback - start 2nd stage
  void
  discoverHubStage2(const std::string& message)
  {
    std::cerr << message << std::endl;
    std::cerr << "Stage 2: Trying DNS query with default suffix..." << std::endl;

    _res.retry = 2;
    _res.ndots = 10;

    QueryAnswer queryAnswer;

    int answerSize = res_search("_ndn._udp",
                                ns_c_in,
                                ns_t_srv,
                                queryAnswer.buf,
                                sizeof(queryAnswer));

    // 2nd stage failed - move on to the third stage
    if (answerSize < 0)
    {
      discoverHubStage3("Failed to find NDN router using default suffix DNS query");
    }
    else
    {
      bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
      if (isParsed == false)
      {
        // Failed to parse DNS response, try stage 3
        discoverHubStage3("Failed to parse DNS response");
      }
    }
  }

  // Second stage OnTimeout callback
  void
  discoverHubStage3(const std::string& message)
  {
    std::cerr << message << std::endl;
    std::cerr << "Stage 3: Trying to find home router..." << std::endl;

    KeyChain keyChain;
    Name identity = keyChain.getDefaultIdentity();
    std::string serverName = "_ndn._udp.";

    for (Name::const_reverse_iterator i = identity.rbegin(); i != identity.rend(); i++)
    {
      serverName.append(i->toUri());
      serverName.append(".");
    }
    serverName += "_homehub._autoconf.named-data.net";
    std::cerr << "Stage3: About to query for a home router: " << serverName << std::endl;

    QueryAnswer queryAnswer;

    int answerSize = res_query(serverName.c_str(),
                               ns_c_in,
                               ns_t_srv,
                               queryAnswer.buf,
                               sizeof(queryAnswer));


    // 3rd stage failed - abort
    if (answerSize < 0)
    {
      std::cerr << "Failed to find a home router" << std::endl;
      std::cerr << "exit" << std::endl;
    }
    else
    {
      bool isParsed = parseHostAndConnectToHub(queryAnswer, answerSize);
      if (isParsed == false)
      {
        // Failed to parse DNS response
        throw Error("Failed to parse DNS response");
      }
    }

  }

  void
  connectToHub(const std::string& uri)
  {
    std::cerr << "about to connect to: " << uri << std::endl;

    m_controller.start<nfd::FaceCreateCommand>(
      nfd::ControlParameters()
        .setUri(uri),
      bind(&NdnAutoconfig::onHubConnectSuccess, this, _1),
      bind(&NdnAutoconfig::onHubConnectError, this, _1, _2)
    );
  }

  void
  onHubConnectSuccess(const nfd::ControlParameters& resp)
  {
    std::cerr << "Successfully created face: " << resp << std::endl;

    // Register a prefix in RIB
    static const Name TESTBED_PREFIX("/ndn");
    m_controller.start<nfd::RibRegisterCommand>(
      nfd::ControlParameters()
        .setName(TESTBED_PREFIX)
        .setFaceId(resp.getFaceId())
        .setOrigin(nfd::ROUTE_ORIGIN_AUTOCONF)
        .setCost(100)
        .setExpirationPeriod(time::milliseconds::max()),
      bind(&NdnAutoconfig::onPrefixRegistrationSuccess, this, _1),
      bind(&NdnAutoconfig::onPrefixRegistrationError, this, _1, _2));
  }

  void
  onHubConnectError(uint32_t code, const std::string& error)
  {
    std::ostringstream os;
    os << "Failed to create face: " << error << " (code: " << code << ")";
    throw Error(os.str());
  }


  bool parseHostAndConnectToHub(QueryAnswer& queryAnswer, int answerSize)
  {
    // The references of the next classes are:
    // http://www.diablotin.com/librairie/networking/dnsbind/ch14_02.htm
    // https://gist.github.com/mologie/6027597

    struct rechdr
    {
      uint16_t type;
      uint16_t iclass;
      uint32_t ttl;
      uint16_t length;
    };

    struct srv_t
    {
      uint16_t priority;
      uint16_t weight;
      uint16_t port;
      uint8_t* target;
    };

    if (ntohs(queryAnswer.header.ancount) == 0)
    {
      std::cerr << "No records found\n" << std::endl;
      return false;
    }

    uint8_t* blob = queryAnswer.buf + NS_HFIXEDSZ;

    blob += dn_skipname(blob, queryAnswer.buf + answerSize) + NS_QFIXEDSZ;

    for (int i = 0; i < ntohs(queryAnswer.header.ancount); i++)
    {
      char srvName[NS_MAXDNAME];
      int serverNameSize = dn_expand(queryAnswer.buf,               // message pointer
                                     queryAnswer.buf + answerSize,  // end of message
                                     blob,                          // compressed server name
                                     srvName,                       // expanded server name
                                     NS_MAXDNAME);
      if (serverNameSize < 0)
      {
        return false;
      }

      srv_t* server = reinterpret_cast<srv_t*>(&blob[sizeof(rechdr)]);
      uint16_t convertedPort = be16toh(server->port);

      blob += serverNameSize + NS_HFIXEDSZ + NS_QFIXEDSZ;

      char hostName[NS_MAXDNAME];
      int hostNameSize = dn_expand(queryAnswer.buf,               // message pointer
                                   queryAnswer.buf + answerSize,  // end of message
                                   blob,                          // compressed host name
                                   hostName,                      // expanded host name
                                   NS_MAXDNAME);
      if (hostNameSize < 0)
      {
        return false;
      }

      std::string uri = "udp://";
      uri.append(hostName);
      uri.append(":");
      uri.append(boost::lexical_cast<std::string>(convertedPort));

      connectToHub(uri);
      return true;
    }

    return false;
  }

  void
  onPrefixRegistrationSuccess(const nfd::ControlParameters& commandSuccessResult)
  {
    std::cerr << "Successful in name registration: " << commandSuccessResult << std::endl;
  }

  void
  onPrefixRegistrationError(uint32_t code, const std::string& error)
  {
    std::ostringstream os;
    os << "Failed in name registration, " << error << " (code: " << code << ")";
    throw Error(os.str());
  }

private:
  Face m_face;
  nfd::Controller m_controller;
};

} // namespace tools
} // namespace ndn

int
main(int argc, char** argv)
{
  int opt;
  const char* programName = argv[0];

  while ((opt = getopt(argc, argv, "hV")) != -1) {
    switch (opt) {
    case 'h':
      ndn::tools::usage(programName);
      return 0;
    case 'V':
      std::cout << NFD_VERSION_BUILD_STRING << std::endl;
      return 0;
    }
  }

  try {
    ndn::tools::NdnAutoconfig autoConfigInstance;

    autoConfigInstance.discoverHubStage1();
    autoConfigInstance.run();
  }
  catch (const std::exception& error) {
    std::cerr << "ERROR: " << error.what() << std::endl;
    return 1;
  }
  return 0;
}
