/* -*- 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 "database-test-data.hpp"
#include "logger.hpp"

#include <boost/filesystem.hpp>

namespace ndn {
namespace ndns {
namespace tests {
NDNS_LOG_INIT("TestFakeData")

const boost::filesystem::path DbTestData::TEST_DATABASE = TEST_CONFIG_PATH "/" "test-ndns.db";
const Name DbTestData::TEST_IDENTITY_NAME("/test19");
const boost::filesystem::path DbTestData::TEST_CERT =
  TEST_CONFIG_PATH "/" "anchors/root.cert";

DbTestData::PreviousStateCleaner::PreviousStateCleaner()
{
  boost::filesystem::remove(TEST_DATABASE);
  boost::filesystem::remove(TEST_CERT);
}

DbTestData::DbTestData()
  : m_session(TEST_DATABASE.string())
  , m_keyChain("sqlite3", "file")
{
  NDNS_LOG_TRACE("start creating test data");

  ndns::Validator::VALIDATOR_CONF_FILE = TEST_CONFIG_PATH "/" "validator.conf";

  m_keyChain.deleteIdentity(TEST_IDENTITY_NAME);
  m_certName = m_keyChain.createIdentity(TEST_IDENTITY_NAME);

  ndn::io::save(*(m_keyChain.getCertificate(m_certName)), TEST_CERT.string());
  NDNS_LOG_INFO("save test root cert " << m_certName << " to: " << TEST_CERT.string());

  BOOST_CHECK_GT(m_certName.size(), 0);
  NDNS_LOG_TRACE("test certName: " << m_certName);

  m_root = Zone(TEST_IDENTITY_NAME);
  Name name(TEST_IDENTITY_NAME);
    name.append("net");
  m_net = Zone(name);
  name.append("ndnsim");
  m_ndnsim =Zone(name);

  m_session.insert(m_root);
  BOOST_CHECK_GT(m_root.getId(), 0);
  m_session.insert(m_net);
  BOOST_CHECK_GT(m_net.getId(), 0);
  m_session.insert(m_ndnsim);
  BOOST_CHECK_GT(m_ndnsim.getId(), 0);

  m_zones.push_back(m_root);
  m_zones.push_back(m_net);
  m_zones.push_back(m_ndnsim);

  int certificateIndex = 0;
  function<void(const Name&,Zone&,const name::Component&)> addQueryRrset =
    [this, &certificateIndex] (const Name& label, Zone& zone,
                               const name::Component& type) {
    const time::seconds ttl(3000 + 100 * certificateIndex);
    const name::Component version = name::Component::fromVersion(100 + 1000 * certificateIndex);
    name::Component qType(label::NDNS_ITERATIVE_QUERY);
    NdnsType ndnsType = NDNS_RESP;
    if (type == label::CERT_RR_TYPE) {
      ndnsType = NDNS_RAW;
      qType = label::NDNS_CERT_QUERY;
    }
    std::ostringstream os;
    os << "a fake content: " << (++certificateIndex) << "th";

    addRrset(zone, label, type, ttl, version, qType, ndnsType, os.str());
  };

  addQueryRrset("/dsk-1", m_root, label::CERT_RR_TYPE);
  addQueryRrset("/net/ksk-2", m_root, label::CERT_RR_TYPE);
  addQueryRrset("/dsk-3", m_net, label::CERT_RR_TYPE);
  addQueryRrset("/ndnsim/ksk-4", m_net, label::CERT_RR_TYPE);
  addQueryRrset("/dsk-5", m_ndnsim, label::CERT_RR_TYPE);

  addQueryRrset("net", m_root, label::NS_RR_TYPE);
  addQueryRrset("ndnsim", m_net, label::NS_RR_TYPE);
  addQueryRrset("www", m_ndnsim, label::TXT_RR_TYPE);
  addQueryRrset("doc/www", m_ndnsim, label::TXT_RR_TYPE);


  addRrset(m_ndnsim, Name("doc"), label::NS_RR_TYPE , time::seconds(2000),
           name::Component::fromVersion(1234), label::NDNS_ITERATIVE_QUERY, NDNS_AUTH,
           std::string(""));

  NDNS_LOG_INFO("insert testing data: OK");
}

void
DbTestData::addRrset(Zone& zone, const Name& label, const name::Component& type,
                     const time::seconds& ttl, const name::Component& version,
                     const name::Component& qType, NdnsType ndnsType, const std::string& msg)
{
  Rrset rrset(&zone);
  rrset.setLabel(label);
  rrset.setType(type);
  rrset.setTtl(ttl);
  rrset.setVersion(version);

  Response re;
  re.setZone(zone.getName());
  re.setQueryType(qType);
  re.setRrLabel(label);
  re.setRrType(type);
  re.setVersion(version);
  re.setNdnsType(ndnsType);
  re.setFreshnessPeriod(ttl);

  if (msg.size() > 0) {
    if (type == label::CERT_RR_TYPE)
      re.setAppContent(dataBlock(ndn::tlv::Content, msg.c_str(), msg.size()));
    else
      re.addRr(msg);
  }
  shared_ptr<Data> data = re.toData();
  m_keyChain.sign(*data, m_certName); // now we ignore the certificate to sign the data
  shared_ptr<IdentityCertificate> cert = m_keyChain.getCertificate(m_certName);
  BOOST_CHECK_EQUAL(Validator::verifySignature(*data, cert->getPublicKeyInfo()), true);
  rrset.setData(data->wireEncode());

  m_session.insert(rrset);

  m_rrsets.push_back(rrset);
}

DbTestData::~DbTestData()
{
  for (auto& zone : m_zones)
    m_session.remove(zone);

  for (auto& rrset : m_rrsets)
    m_session.remove(rrset);

  m_session.close();
}

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