/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014, Regents of the University of California.
 *
 * This file is part of NDNS (Named Data Networking Domain Name Service).
 * See AUTHORS.md for complete list of NDNS authors and contributors.
 *
 * NDNS 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.
 *
 * NDNS 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
 * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "daemon/db-mgr.hpp"
#include "daemon/name-server.hpp"
#include "clients/response.hpp"
#include "clients/query.hpp"
#include "logger.hpp"

#include "../database-test-data.hpp"
#include "../../boost-test.hpp"

#include <boost/filesystem.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>

namespace ndn {
namespace ndns {
namespace tests {

NDNS_LOG_INIT("NameServerTest");

class NameServerFixture : public DbTestData
{
public:
  NameServerFixture()
    : face(ndn::util::makeDummyClientFace({ false, true }))
    , zone(m_root.getName())
    , validator(*face)
    , server(zone, m_certName, *face, m_session, m_keyChain, validator)
  {
    // ensure prefix is registered
    run();
  }

  void
  run()
  {
    face->getIoService().poll();
    face->getIoService().reset();
  }

public:
  shared_ptr<ndn::util::DummyClientFace> face;
  Name hint;
  const Name& zone;
  Validator validator;
  ndns::NameServer server;
};

BOOST_FIXTURE_TEST_SUITE(NameServer, NameServerFixture)

BOOST_AUTO_TEST_CASE(NdnsQuery)
{
  Query q(hint, zone, ndns::label::NDNS_ITERATIVE_QUERY);
  q.setRrLabel(Name("net"));
  q.setRrType(ndns::label::NS_RR_TYPE);

  bool hasDataBack = false;

  face->onData += [&] (const Data& data) {
    hasDataBack = true;
    NDNS_LOG_TRACE("get Data back");
    BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());

    Response resp;
    BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
    BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP);
  };

  face->receive(q.toInterest());

  run();

  BOOST_CHECK_EQUAL(hasDataBack, true);
}

BOOST_AUTO_TEST_CASE(KeyQuery)
{
  Query q(hint, zone, ndns::label::NDNS_ITERATIVE_QUERY);
  q.setQueryType(ndns::label::NDNS_CERT_QUERY);
  q.setRrType(ndns::label::CERT_RR_TYPE);

  size_t nDataBack = 0;

  // will ask for non-existing record
  face->onData += [&] (const Data& data) {
    ++nDataBack;
    NDNS_LOG_TRACE("get Data back");
    BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());

    Response resp;
    BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
    BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_NACK);
  };

  face->receive(q.toInterest());
  run();

  // will ask for the existing record (will have type NDNS_RAW, as it is certificate)
  face->onData.clear();
  face->onData += [&] (const Data& data) {
    ++nDataBack;
    NDNS_LOG_TRACE("get Data back");
    BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());

    Response resp;
    BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
    BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RAW);
  };

  q.setRrLabel("dsk-1");

  face->receive(q.toInterest());
  run();

  BOOST_CHECK_EQUAL(nDataBack, 2);
}

BOOST_AUTO_TEST_CASE(UpdateReplaceRr)
{
  Response re;
  re.setZone(zone);
  re.setQueryType(label::NDNS_ITERATIVE_QUERY);
  re.setRrLabel(Name("net"));
  re.setRrType(label::NS_RR_TYPE);
  re.setNdnsType(NDNS_RESP);

  std::string str = "ns1.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
  str = "ns2.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));

  shared_ptr<Data> data = re.toData();
  m_keyChain.sign(*data, m_certName);

  Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
  const Block& block = data->wireEncode();
  Name name;
  name.append(block);

  q.setRrLabel(name);
  q.setRrType(label::NDNS_UPDATE_LABEL);

  bool hasDataBack = false;

  face->onData += [&] (const Data& data) {
    hasDataBack = true;
    NDNS_LOG_TRACE("get Data back");
    BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
    Response resp;

    BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
    BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
    BOOST_CHECK_GT(resp.getRrs().size(), 0);
    Block block = resp.getRrs()[0];
    block.parse();
    int ret = -1;
    BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
    Block::element_const_iterator val = block.elements_begin();
    BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
    ret = readNonNegativeInteger(*val);
    BOOST_CHECK_EQUAL(ret, 0);
  };

  face->receive(q.toInterest());
  run();

  BOOST_CHECK_EQUAL(hasDataBack, true);
}

BOOST_AUTO_TEST_CASE(UpdateInsertNewRr)
{
  Response re;
  re.setZone(zone);
  re.setQueryType(label::NDNS_ITERATIVE_QUERY);
  re.setRrLabel(Name("net-XYZ")); // insert new records
  re.setRrType(label::NS_RR_TYPE);
  re.setNdnsType(NDNS_RESP);

  std::string str = "ns1.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
  str = "ns2.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));

  shared_ptr<Data> data = re.toData();
  m_keyChain.sign(*data, m_certName);

  Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
  const Block& block = data->wireEncode();
  Name name;
  name.append(block);

  q.setRrLabel(name);
  q.setRrType(label::NDNS_UPDATE_LABEL);

  bool hasDataBack = false;

  face->onData += [&] (const Data& data) {
    hasDataBack = true;
    NDNS_LOG_TRACE("get Data back");
    BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
    Response resp;

    BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
    BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
    BOOST_CHECK_GT(resp.getRrs().size(), 0);
    Block block = resp.getRrs()[0];
    block.parse();
    int ret = -1;
    BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
    Block::element_const_iterator val = block.elements_begin();
    BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
    ret = readNonNegativeInteger(*val);
    BOOST_CHECK_EQUAL(ret, 0);
  };

  face->receive(q.toInterest());
  run();

  BOOST_CHECK_EQUAL(hasDataBack, true);
}

BOOST_AUTO_TEST_CASE(UpdateValidatorCannotFetchCert)
{
  Name dskName = m_keyChain.generateRsaKeyPair(TEST_IDENTITY_NAME, false);
  std::vector<CertificateSubjectDescription> desc;
  time::system_clock::TimePoint notBefore = time::system_clock::now();
  time::system_clock::TimePoint notAfter = notBefore + time::days(365);
  shared_ptr<IdentityCertificate> dskCert =
    m_keyChain.prepareUnsignedIdentityCertificate(dskName, m_certName,
                                                  notBefore, notAfter, desc);

  m_keyChain.sign(*dskCert, m_certName);
  m_keyChain.addCertificateAsKeyDefault(*dskCert);
  NDNS_LOG_TRACE("KeyChain: add cert: " << dskCert->getName() << ". KeyLocator: "
                 << dskCert->getSignature().getKeyLocator().getName());

  Rrset rrset(&m_root);
  Name label = dskCert->getName().getPrefix(-2).getSubName(m_root.getName().size() + 1);
  rrset.setLabel(label);
  rrset.setType(label::CERT_RR_TYPE);
  rrset.setVersion(dskCert->getName().get(-1));
  rrset.setTtl(m_root.getTtl());
  rrset.setData(dskCert->wireEncode());
  m_session.insert(rrset);
  NDNS_LOG_TRACE("DB: zone " << m_root << " add a ID-CERT RR with name="
                 << dskCert->getName() << " rrLabel=" << label);

  Response re;
  re.setZone(zone);
  re.setQueryType(label::NDNS_ITERATIVE_QUERY);
  re.setRrLabel(Name("ndnsim-XYZ")); // insert new records
  re.setRrType(label::NS_RR_TYPE);
  re.setNdnsType(NDNS_RESP);

  std::string str = "ns1.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
  str = "ns2.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));

  shared_ptr<Data> data = re.toData();
  m_keyChain.sign(*data, dskCert->getName());

  Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
  const Block& block = data->wireEncode();
  Name name;
  name.append(block);

  q.setRrLabel(name);
  q.setRrType(label::NDNS_UPDATE_LABEL);

  bool hasDataBack = false;

  // no data back, since the Update cannot pass verification
  face->onData += [&] (const Data& data) {
    hasDataBack = true;
    BOOST_FAIL("UNEXPECTED");
  };

  face->receive(q.toInterest());
  run();

  BOOST_CHECK_EQUAL(hasDataBack, false);
}

class NameServerFixture2 : public DbTestData
{
public:
  NameServerFixture2()
    : face(ndn::util::makeDummyClientFace(io, { false, true }))
    , validatorFace(ndn::util::makeDummyClientFace(io, { false, true }))
    , zone(m_root.getName())
    , validator(*validatorFace) // different face for validator
    , server(zone, m_certName, *face, m_session, m_keyChain, validator)
  {
    // ensure prefix is registered
    run();
    validatorFace->onInterest += [&] (const Interest& interest) {
      NDNS_LOG_TRACE("validatorFace get Interest: " << interest.getName());
      face->receive(interest);
    };
  }

  void
  run()
  {
    io.poll();
    io.reset();
  }

public:
  boost::asio::io_service io;
  shared_ptr<ndn::util::DummyClientFace> face;
  shared_ptr<ndn::util::DummyClientFace> validatorFace;
  Name hint;
  const Name& zone;
  Validator validator;
  ndns::NameServer server;
};

BOOST_FIXTURE_TEST_CASE(UpdateValidatorFetchCert, NameServerFixture2)
{
  Name dskName = m_keyChain.generateRsaKeyPair(TEST_IDENTITY_NAME, false);
  std::vector<CertificateSubjectDescription> desc;
  time::system_clock::TimePoint notBefore = time::system_clock::now();
  time::system_clock::TimePoint notAfter = notBefore + time::days(365);
  shared_ptr<IdentityCertificate> dskCert =
    m_keyChain.prepareUnsignedIdentityCertificate(dskName, m_certName,
                                                  notBefore, notAfter, desc);

  m_keyChain.sign(*dskCert, m_certName);
  m_keyChain.addCertificateAsKeyDefault(*dskCert);
  NDNS_LOG_TRACE("KeyChain: add cert: " << dskCert->getName() << ". KeyLocator: "
                 << dskCert->getSignature().getKeyLocator().getName());

  Rrset rrset(&m_root);
  Name label = dskCert->getName().getPrefix(-2).getSubName(m_root.getName().size() + 1);
  rrset.setLabel(label);
  rrset.setType(label::CERT_RR_TYPE);
  rrset.setVersion(dskCert->getName().get(-1));
  rrset.setTtl(m_root.getTtl());
  rrset.setData(dskCert->wireEncode());
  m_session.insert(rrset);
  NDNS_LOG_TRACE("DB: zone " << m_root << " add a ID-CERT RR with name="
                 << dskCert->getName() << " rrLabel=" << label);

  Response re;
  re.setZone(zone);
  re.setQueryType(label::NDNS_ITERATIVE_QUERY);
  re.setRrLabel(Name("ndnsim-XYZ")); // insert new records
  re.setRrType(label::NS_RR_TYPE);
  re.setNdnsType(NDNS_RESP);

  std::string str = "ns1.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));
  str = "ns2.ndnsim.net";
  re.addRr(dataBlock(ndns::tlv::RrData, str.c_str(), str.size()));

  shared_ptr<Data> data = re.toData();
  m_keyChain.sign(*data, dskCert->getName());

  Query q(Name(hint), Name(zone), ndns::label::NDNS_ITERATIVE_QUERY);
  const Block& block = data->wireEncode();
  Name name;
  name.append(block);

  q.setRrLabel(name);
  q.setRrType(label::NDNS_UPDATE_LABEL);

  bool hasDataBack = false;

  shared_ptr<Regex> regex = make_shared<Regex>("(<>*)<KEY>(<>+)<ID-CERT><>");
  face->onData += [&] (const Data& data) {
    if (regex->match(data.getName())) {
      validatorFace->receive(data); // It's data requested by validator
    }
    else {
      // cert is requested by validator
      hasDataBack = true;
      NDNS_LOG_TRACE("get Data back");
      BOOST_CHECK_EQUAL(data.getName().getPrefix(-1), q.toInterest().getName());
      Response resp;

      BOOST_CHECK_NO_THROW(resp.fromData(hint, zone, data));
      BOOST_CHECK_EQUAL(resp.getNdnsType(), NDNS_RESP); // by default NDNS_RAW is enough
      BOOST_CHECK_GT(resp.getRrs().size(), 0);
      Block block = resp.getRrs()[0];
      block.parse();
      int ret = -1;
      BOOST_CHECK_EQUAL(block.type(), ndns::tlv::RrData);
      Block::element_const_iterator val = block.elements_begin();
      BOOST_CHECK_EQUAL(val->type(), ndns::tlv::UpdateReturnCode); // the first must be return code
      ret = readNonNegativeInteger(*val);
      BOOST_CHECK_EQUAL(ret, 0);
    }
  };

  face->receive(q.toInterest());
  run();

  BOOST_CHECK_EQUAL(hasDataBack, true);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace ndns
} // namespace ndn
