/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013-2021, Regents of the University of California
 *                          Yingdi Yu
 *
 * BSD license, See the LICENSE file for more information
 *
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 *         Qiuhan Ding <qiuhanding@cs.ucla.edu>
 */

#include "contact-manager.hpp"

#include <QStringList>
#include <QFile>

#ifndef Q_MOC_RUN
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>
#include <ndn-cxx/security/transform/buffer-source.hpp>
#include <ndn-cxx/security/transform/digest-filter.hpp>
#include <ndn-cxx/security/transform/stream-sink.hpp>
#include <ndn-cxx/security/validator.hpp>
#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/security/verification-helpers.hpp>

#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/tokenizer.hpp>
#endif

namespace fs = boost::filesystem;

namespace chronochat {

using std::string;
using std::map;
using std::vector;

using ndn::Face;
using ndn::OBufferStream;
using ndn::security::Certificate;


ContactManager::ContactManager(Face& face,
                               ndn::KeyChain& keyChain,
                               QObject* parent)
  : QObject(parent)
  , m_face(face)
  , m_keyChain(keyChain)
{
  initializeSecurity();
}

ContactManager::~ContactManager()
{
}

void
ContactManager::initializeSecurity()
{
  m_validator = std::make_shared<ndn::security::ValidatorConfig>(m_face);
  m_validator->load("security/validation-contact-manager.conf");
}

void
ContactManager::fetchCollectEndorse(const Name& identity)
{
  Name interestName = identity;
  interestName.append("DNS").append("ENDORSED");

  Interest interest(interestName);
  interest.setInterestLifetime(time::milliseconds(1000));
  interest.setCanBePrefix(true);
  interest.setMustBeFresh(true);

  ndn::security::DataValidationSuccessCallback onValidated =
    bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
  ndn::security::DataValidationFailureCallback onValidationFailed =
    bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, _2, identity);
  TimeoutNotify timeoutNotify =
    bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, _1, identity);

  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}

void
ContactManager::fetchEndorseCertificateInternal(const Name& identity, size_t certIndex)
{
  auto endorseCollection = m_bufferedContacts[identity].m_endorseCollection;

  if (certIndex >= endorseCollection->getCollectionEntries().size())
    return prepareEndorseInfo(identity);

  Name interestName(endorseCollection->getCollectionEntries()[certIndex].certName);

  Interest interest(interestName);
  interest.setInterestLifetime(time::milliseconds(1000));
  interest.setCanBePrefix(true);
  interest.setMustBeFresh(false);

  m_face.expressInterest(interest,
                         bind(&ContactManager::onEndorseCertificateInternal,
                              this, _1, _2, identity, certIndex,
                              endorseCollection->getCollectionEntries()[certIndex].hash),
                         bind(&ContactManager::onEndorseCertificateInternalTimeout,
                              this, _1, identity, certIndex),
                         bind(&ContactManager::onEndorseCertificateInternalTimeout,
                              this, _1, identity, certIndex));
}

void
ContactManager::prepareEndorseInfo(const Name& identity)
{
  const Profile& profile = m_bufferedContacts[identity].m_selfEndorseCert->getProfile();

  auto endorseInfo = std::make_shared<EndorseInfo>();
  m_bufferedContacts[identity].m_endorseInfo = endorseInfo;

  map<string, size_t> endorseCount;
  for (auto pIt = profile.begin(); pIt != profile.end(); pIt++)
    endorseCount[pIt->first] = 0;

  size_t endorseCertCount = 0;

  auto cIt = m_bufferedContacts[identity].m_endorseCertList.cbegin();
  auto cEnd = m_bufferedContacts[identity].m_endorseCertList.cend();

  for (; cIt != cEnd; cIt++, endorseCertCount++) {
    shared_ptr<Contact> contact = getContact((*cIt)->getSigner());
    if (!static_cast<bool>(contact))
      continue;

    if (!contact->isIntroducer() ||
        !contact->canBeTrustedFor(profile.getIdentityName()))
      continue;

    if (!(*cIt)->isValid())
      continue;

    if (!ndn::security::verifySignature(**cIt, contact->getPublicKey().data(), contact->getPublicKey().size()))
      continue;

    const Profile& tmpProfile = (*cIt)->getProfile();
    const auto& endorseList = (*cIt)->getEndorseList();
    for (auto eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
      if (tmpProfile.get(*eIt) == profile.get(*eIt))
        endorseCount[*eIt] += 1;
  }

  for (auto pIt = profile.begin(); pIt != profile.end(); pIt++) {
    std::stringstream ss;
    ss << endorseCount[pIt->first] << "/" << endorseCertCount;
    endorseInfo->addEndorsement(pIt->first, pIt->second, ss.str());
  }

  emit contactEndorseInfoReady (*endorseInfo);
}

void
ContactManager::onDnsSelfEndorseCertValidated(const Data& data,
                                              const Name& identity)
{
  try {
    Data plainData;
    plainData.wireDecode(data.getContent().blockFromValue());
    auto selfEndorseCertificate = std::make_shared<EndorseCertificate>(plainData);

    if (ndn::security::verifySignature(plainData, *selfEndorseCertificate)) {
      m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
      fetchCollectEndorse(identity);
    }
    else
      emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": verification failed"));
  }
  catch (const Block::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": block error " + e.what()));
  }
  catch (const EndorseCertificate::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": cert error " + e.what()));
  }
  catch (const Data::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri() + ": data error " + e.what()));
  }
}

void
ContactManager::onDnsSelfEndorseCertValidationFailed(const Data& data,
                                                     const ndn::security::ValidationError& error,
                                                     const Name& identity)
{
  // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
  // but let's stay with failure for now.
  emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}

void
ContactManager::onDnsSelfEndorseCertTimeoutNotify(const Interest& interest,
                                                  const Name& identity)
{
  // If we cannot validate the Self-Endorse-Certificate, we may retry or fetch id-cert,
  // but let's stay with failure for now.
  emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
}

void
ContactManager::onDnsCollectEndorseValidated(const Data& data,
                                             const Name& identity)
{
  try {
    auto endorseCollection = std::make_shared<EndorseCollection>(data.getContent().blockFromValue());
    m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
    fetchEndorseCertificateInternal(identity, 0);
  }
  catch (const std::runtime_error&) {
    prepareEndorseInfo(identity);
  }
}

void
ContactManager::onDnsCollectEndorseValidationFailed(const Data& data,
                                                    const ndn::security::ValidationError& error,
                                                    const Name& identity)
{
  prepareEndorseInfo(identity);
}

void
ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest, const Name& identity)
{
  prepareEndorseInfo(identity);
}

void
ContactManager::onEndorseCertificateInternal(const Interest&, const Data& data,
                                             const Name& identity, size_t certIndex, string hash)
{
  std::ostringstream ss;
  {
    using namespace ndn::security::transform;
    bufferSource(data.wireEncode().wire(), data.wireEncode().size())
        >> digestFilter(ndn::DigestAlgorithm::SHA256)
        >> streamSink(ss);
  }

  if (ss.str() == hash) {
    auto endorseCertificate = std::make_shared<EndorseCertificate>(data);
    m_bufferedContacts[identity].m_endorseCertList.push_back(std::move(endorseCertificate));
  }

  fetchEndorseCertificateInternal(identity, certIndex+1);
}

void
ContactManager::onEndorseCertificateInternalTimeout(const Interest& interest,
                                                    const Name& identity,
                                                    size_t certIndex)
{
  fetchEndorseCertificateInternal(identity, certIndex+1);
}

void
ContactManager::collectEndorsement()
{
  {
    boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
    m_collectCount = m_contactList.size();

    for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
      Name interestName = (*it)->getNameSpace();
      interestName.append("DNS").append(m_identity.wireEncode()).append("ENDORSEE");

      Interest interest(interestName);
      interest.setMustBeFresh(true);
      interest.setCanBePrefix(true);
      interest.setInterestLifetime(time::milliseconds(1000));

      ndn::security::DataValidationSuccessCallback onValidated =
        bind(&ContactManager::onDnsEndorseeValidated, this, _1);
      ndn::security::DataValidationFailureCallback onValidationFailed =
        bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1, _2);
      TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);

      sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
    }
  }
}

void
ContactManager::onDnsEndorseeValidated(const Data& data)
{
  Data endorseData;
  endorseData.wireDecode(data.getContent().blockFromValue());

  EndorseCertificate endorseCertificate(endorseData);
  m_contactStorage->updateCollectEndorse(endorseCertificate);

  decreaseCollectStatus();
}

void
ContactManager::onDnsEndorseeValidationFailed(const Data& data,
                                              const ndn::security::ValidationError& error)
{
  decreaseCollectStatus();
}

void
ContactManager::onDnsEndorseeTimeoutNotify(const Interest& interest)
{
  decreaseCollectStatus();
}

void
ContactManager::decreaseCollectStatus()
{
  size_t count;
  {
    boost::recursive_mutex::scoped_lock lock(m_collectCountMutex);
    m_collectCount--;
    count = m_collectCount;
  }

  if(count == 0)
    publishCollectEndorsedDataInDNS();
}

void
ContactManager::publishCollectEndorsedDataInDNS()
{
  Name dnsName = m_identity;
  dnsName.append("DNS").append("ENDORSED").appendVersion();

  auto data = std::make_shared<Data>();
  data->setName(dnsName);
  data->setFreshnessPeriod(time::milliseconds(1000));

  EndorseCollection endorseCollection;
  m_contactStorage->getCollectEndorse(endorseCollection);

  data->setContent(endorseCollection.wireEncode());

  m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));

  m_contactStorage->updateDnsOthersEndorse(*data);
  m_face.put(*data);
}

void
ContactManager::onIdentityCertValidated(const Data& data)
{
  auto cert = std::make_shared<Certificate>(data);
  m_bufferedIdCerts[cert->getName()] = cert;
  decreaseIdCertCount();
}

void
ContactManager::onIdentityCertValidationFailed(const Data& data,
                                               const ndn::security::ValidationError& error)
{
  decreaseIdCertCount();
}

void
ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
{
  decreaseIdCertCount();
}

void
ContactManager::decreaseIdCertCount()
{
  size_t count;
  {
    boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
    m_idCertCount--;
    count = m_idCertCount;
  }

  if (count == 0) {
    QStringList certNameList;
    QStringList nameList;

    for (auto it = m_bufferedIdCerts.begin(); it != m_bufferedIdCerts.end(); it++) {
      certNameList << QString::fromStdString(it->second->getName().toUri());
      Profile profile(*(it->second));
      nameList << QString::fromStdString(profile.get("name"));
    }

    emit idCertNameListReady(certNameList);
    emit nameListReady(nameList);
  }
}

shared_ptr<EndorseCertificate>
ContactManager::getSignedSelfEndorseCertificate(const Profile& profile)
{
  auto signCert = m_keyChain.getPib().getIdentity(m_identity)
                            .getDefaultKey().getDefaultCertificate();
  vector<string> endorseList;
  for (auto it = profile.begin(); it != profile.end(); it++)
    endorseList.push_back(it->first);

  auto selfEndorseCertificate = std::make_shared<EndorseCertificate>(signCert, profile, endorseList);

  m_keyChain.sign(*selfEndorseCertificate,
                  ndn::security::signingByIdentity(m_identity).setSignatureInfo(
                    selfEndorseCertificate->getSignatureInfo()));

  return selfEndorseCertificate;
}

void
ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
{
  Name dnsName = m_identity;
  dnsName.append("DNS").append("PROFILE").appendVersion();

  auto data = std::make_shared<Data>();
  data->setName(dnsName);
  data->setContent(selfEndorseCertificate.wireEncode());
  data->setFreshnessPeriod(time::milliseconds(1000));

  m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));

  m_contactStorage->updateDnsSelfProfileData(*data);
  m_face.put(*data);
}

shared_ptr<EndorseCertificate>
ContactManager::generateEndorseCertificate(const Name& identity)
{
  auto signCert = m_keyChain.getPib().getIdentity(m_identity)
                            .getDefaultKey().getDefaultCertificate();

  shared_ptr<Contact> contact = getContact(identity);
  if (!static_cast<bool>(contact))
    return shared_ptr<EndorseCertificate>();

  Name signerKeyName = m_identity;

  vector<string> endorseList;
  m_contactStorage->getEndorseList(identity, endorseList);

  shared_ptr<EndorseCertificate> cert =
    shared_ptr<EndorseCertificate>(new EndorseCertificate(contact->getPublicKeyName(),
                                                          contact->getPublicKey(),
                                                          contact->getNotBefore(),
                                                          contact->getNotAfter(),
                                                          signCert.getKeyId(),
                                                          signerKeyName,
                                                          contact->getProfile(),
                                                          endorseList));
  m_keyChain.sign(*cert,
                  ndn::security::signingByIdentity(m_identity)
                    .setSignatureInfo(cert->getSignatureInfo()));
  return cert;

}

void
ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate)
{
  Name endorsee = endorseCertificate.getKeyName().getPrefix(-4);
  Name dnsName = m_identity;
  dnsName.append("DNS")
    .append(endorsee.wireEncode())
    .append("ENDORSEE")
    .appendVersion();

  auto data = std::make_shared<Data>();
  data->setName(dnsName);
  data->setContent(endorseCertificate.wireEncode());
  data->setFreshnessPeriod(time::milliseconds(1000));

  m_keyChain.sign(*data, ndn::security::signingByIdentity(m_identity));

  m_contactStorage->updateDnsEndorseOthers(*data, dnsName.get(-3).toUri());
  m_face.put(*data);
}

void
ContactManager::sendInterest(const Interest& interest,
                             const ndn::security::DataValidationSuccessCallback& onValidated,
                             const ndn::security::DataValidationFailureCallback& onValidationFailed,
                             const TimeoutNotify& timeoutNotify,
                             int retry /* = 1 */)
{
  m_face.expressInterest(interest,
                         bind(&ContactManager::onTargetData,
                              this, _1, _2, onValidated, onValidationFailed),
                         bind(&ContactManager::onTargetTimeout,
                              this, _1, retry, onValidated, onValidationFailed, timeoutNotify),
                         bind(&ContactManager::onTargetTimeout,
                              this, _1, retry, onValidated, onValidationFailed, timeoutNotify));
}

void
ContactManager::onTargetData(const Interest& interest,
                             const Data& data,
                             const ndn::security::DataValidationSuccessCallback& onValidated,
                             const ndn::security::DataValidationFailureCallback& onValidationFailed)
{
  m_validator->validate(data, onValidated, onValidationFailed);
}

void
ContactManager::onTargetTimeout(const Interest& interest,
                                int retry,
                                const ndn::security::DataValidationSuccessCallback& onValidated,
                                const ndn::security::DataValidationFailureCallback& onValidationFailed,
                                const TimeoutNotify& timeoutNotify)
{
  if (retry > 0)
    sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, retry-1);
  else
    timeoutNotify(interest);
}

void
ContactManager::onDnsInterest(const Name& prefix, const Interest& interest)
{
  const Name& interestName = interest.getName();
  shared_ptr<Data> data;

  if (interestName.size() <= prefix.size())
    return;

  if (interestName.size() == (prefix.size()+1)) {
    data = m_contactStorage->getDnsData("N/A", interestName.get(prefix.size()).toUri());
    if (static_cast<bool>(data))
      m_face.put(*data);
    return;
  }

  if (interestName.size() == (prefix.size()+2)) {
    data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toUri(),
                                        interestName.get(prefix.size()+1).toUri());
    if (static_cast<bool>(data))
      m_face.put(*data);
    return;
  }
}

void
ContactManager::onDnsRegisterFailed(const Name& prefix, const std::string& failInfo)
{
  emit warning(QString(failInfo.c_str()));
}

void
ContactManager::onKeyInterest(const Name& prefix, const Interest& interest)
{
  const Name& interestName = interest.getName();
  shared_ptr<Certificate> data;

  try {
    ndn::security::Certificate cert = m_keyChain.getPib()
                                                .getIdentity(m_identity)
                                                .getDefaultKey()
                                                .getDefaultCertificate();
    if (cert.getKeyName() == interestName)
      return m_face.put(cert);
  } catch (const ndn::security::Pib::Error&) {}

  data = m_contactStorage->getSelfEndorseCertificate();
  if (static_cast<bool>(data) && data->getKeyName().equals(interestName))
    return m_face.put(*data);

  data = m_contactStorage->getCollectEndorseByName(interestName);
  if (static_cast<bool>(data))
    return m_face.put(*data);
}

// public slots
void
ContactManager::onIdentityUpdated(const QString& identity)
{
  m_identity = Name(identity.toStdString());

  m_contactStorage = std::make_shared<ContactStorage>(m_identity);

  m_dnsListenerHandle = m_face.setInterestFilter(
    Name(m_identity).append("DNS"),
    bind(&ContactManager::onDnsInterest, this, _1, _2),
    bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));

  m_keyListenerHandle = m_face.setInterestFilter(
    Name(m_identity).append("KEY"),
    bind(&ContactManager::onKeyInterest, this, _1, _2),
    bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));

  m_profileCertListenerHandle = m_face.setInterestFilter(
    Name(m_identity).append("PROFILE-CERT"),
    bind(&ContactManager::onKeyInterest, this, _1, _2),
    bind(&ContactManager::onDnsRegisterFailed, this, _1, _2));

  m_contactList.clear();
  m_contactStorage->getAllContacts(m_contactList);

  m_bufferedContacts.clear();
  onWaitForContactList();

  collectEndorsement();
}

void
ContactManager::onFetchContactInfo(const QString& identity)
{
  // try to fetch self-endorse-certificate via DNS PROFILE first.
  Name identityName(identity.toStdString());
  Name interestName;
  interestName.append(identityName).append("DNS").append("PROFILE");

  Interest interest(interestName);
  interest.setInterestLifetime(time::milliseconds(1000));
  interest.setCanBePrefix(true);
  interest.setMustBeFresh(true);

  ndn::security::DataValidationSuccessCallback onValidated =
    bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
  ndn::security::DataValidationFailureCallback onValidationFailed =
    bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, _2, identityName);
  TimeoutNotify timeoutNotify =
    bind(&ContactManager::onDnsSelfEndorseCertTimeoutNotify, this, _1, identityName);

  sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
}

void
ContactManager::onAddFetchedContact(const QString& identity)
{
  Name identityName(identity.toStdString());

  auto it = m_bufferedContacts.find(identityName);
  if (it != m_bufferedContacts.end()) {
    Contact contact(*(it->second.m_selfEndorseCert));

    try {
      m_contactStorage->addContact(contact);
      m_bufferedContacts.erase(identityName);

      m_contactList.clear();
      m_contactStorage->getAllContacts(m_contactList);

      onWaitForContactList();
    }
    catch (const ContactStorage::Error& e) {
      emit warning(QString::fromStdString(e.what()));
    }
  }
  else
    emit warning(QString("Failure: no information of %1").arg(identity));
}

void
ContactManager::onUpdateProfile()
{
  // Get current profile;
  shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile();
  if (!static_cast<bool>(newProfile))
    return;

  shared_ptr<EndorseCertificate> newEndorseCertificate =
    getSignedSelfEndorseCertificate(*newProfile);

  m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);

  publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
}

void
ContactManager::onRefreshBrowseContact()
{
  return;

#if 0
  // The following no longer works as we don't serve such a list anymore
  vector<string> bufferedIdCertNames;
  try {
    using namespace boost::asio::ip;
    tcp::iostream request_stream;
    request_stream.expires_from_now(std::chrono::milliseconds(5000));
    request_stream.connect("ndncert.named-data.net","80");
    if (!request_stream) {
      emit warning(QString::fromStdString("Fail to fetch certificate directory! #1"));
      return;
    }

    request_stream << "GET /cert/list/ HTTP/1.0\r\n";
    request_stream << "Host: ndncert.named-data.net\r\n\r\n";
    request_stream.flush();

    string line1;
    std::getline(request_stream,line1);
    if (!request_stream) {
      emit warning(QString::fromStdString("Fail to fetch certificate directory! #2"));
      return;
    }

    std::stringstream response_stream(line1);
    string http_version;
    response_stream >> http_version;
    size_t status_code;
    response_stream >> status_code;
    string status_message;
    std::getline(response_stream,status_message);

    if (!response_stream ||
        http_version.substr(0,5) != "HTTP/") {
      emit warning(QString::fromStdString("Fail to fetch certificate directory! #3"));
      return;
    }
    if (status_code!=200) {
      emit warning(QString::fromStdString("Fail to fetch certificate directory! #4"));
      return;
    }
    vector<string> headers;
    string header;
    while (std::getline(request_stream, header) && header != "\r")
      headers.push_back(header);

    std::istreambuf_iterator<char> stream_iter (request_stream);
    std::istreambuf_iterator<char> end_of_stream;

    typedef boost::tokenizer< boost::escaped_list_separator<char>,
                              std::istreambuf_iterator<char> > tokenizer_t;
    tokenizer_t certItems (stream_iter,
                           end_of_stream,
                           boost::escaped_list_separator<char>('\\', '\n', '"'));

    for (tokenizer_t::iterator it = certItems.begin(); it != certItems.end (); it++)
      if (!it->empty())
        bufferedIdCertNames.push_back(*it);
  }
  catch (const std::exception& e) {
    emit warning(QString::fromStdString("Fail to fetch certificate directory! #N"));
  }

  {
    boost::recursive_mutex::scoped_lock lock(m_idCertCountMutex);
    m_idCertCount = bufferedIdCertNames.size();
  }
  m_bufferedIdCerts.clear();

  for (auto it = bufferedIdCertNames.begin(); it != bufferedIdCertNames.end(); it++) {
    Name certName(*it);

    Interest interest(certName);
    interest.setInterestLifetime(time::milliseconds(1000));
    interest.setMustBeFresh(true);
    interest.setCanBePrefix(true);

    ndn::security::DataValidationSuccessCallback onValidated =
    bind(&ContactManager::onIdentityCertValidated, this, _1);
    ndn::security::DataValidationFailureCallback onValidationFailed =
    bind(&ContactManager::onIdentityCertValidationFailed, this, _1, _2);
    TimeoutNotify timeoutNotify =
    bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);

    sendInterest(interest, onValidated, onValidationFailed, timeoutNotify, 0);
  }
#endif
}

void
ContactManager::onFetchIdCert(const QString& qCertName)
{
  Name certName(qCertName.toStdString());
  if (m_bufferedIdCerts.find(certName) != m_bufferedIdCerts.end())
    emit idCertReady(*m_bufferedIdCerts[certName]);
}

void
ContactManager::onAddFetchedContactIdCert(const QString& qCertName)
{
  Name certName(qCertName.toStdString());
  Name identity = certName.getPrefix(-1);

  auto it = m_bufferedIdCerts.find(certName);
  if (it != m_bufferedIdCerts.end()) {
    Contact contact(*it->second);
    try {
      m_contactStorage->addContact(contact);
      m_bufferedIdCerts.erase(certName);

      m_contactList.clear();
      m_contactStorage->getAllContacts(m_contactList);

      onWaitForContactList();
    }
    catch (const ContactStorage::Error& e) {
      emit warning(QString::fromStdString(e.what()));
    }
  }
  else
    emit warning(QString("Failure: no information of %1")
                 .arg(QString::fromStdString(identity.toUri())));
}

void
ContactManager::onWaitForContactList()
{
  QStringList aliasList;
  QStringList idList;
  for (auto it = m_contactList.begin(); it != m_contactList.end(); it++) {
    aliasList << QString((*it)->getAlias().c_str());
    idList << QString((*it)->getNameSpace().toUri().c_str());
  }

  emit contactAliasListReady(aliasList);
  emit contactIdListReady(idList);
}

void
ContactManager::onWaitForContactInfo(const QString& identity)
{
  for (auto it = m_contactList.begin(); it != m_contactList.end(); it++)
    if ((*it)->getNameSpace().toUri() == identity.toStdString())
      emit contactInfoReady(QString((*it)->getNameSpace().toUri().c_str()),
                            QString((*it)->getName().c_str()),
                            QString((*it)->getInstitution().c_str()),
                            (*it)->isIntroducer());
}

void
ContactManager::onRemoveContact(const QString& identity)
{
  m_contactStorage->removeContact(Name(identity.toStdString()));
  m_contactList.clear();
  m_contactStorage->getAllContacts(m_contactList);

  onWaitForContactList();
}

void
ContactManager::onUpdateAlias(const QString& identity, const QString& alias)
{
  m_contactStorage->updateAlias(Name(identity.toStdString()), alias.toStdString());
  m_contactList.clear();
  m_contactStorage->getAllContacts(m_contactList);

  onWaitForContactList();
}

void
ContactManager::onUpdateIsIntroducer(const QString& identity, bool isIntroducer)
{
  m_contactStorage->updateIsIntroducer(Name(identity.toStdString()), isIntroducer);
}

void
ContactManager::onUpdateEndorseCertificate(const QString& identity)
{
  Name identityName(identity.toStdString());
  shared_ptr<Certificate> newEndorseCertificate = generateEndorseCertificate(identityName);

  if (!static_cast<bool>(newEndorseCertificate))
    return;

  m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);

  publishEndorseCertificateInDNS(*newEndorseCertificate);
}

} // namespace chronochat


#if WAF
#include "contact-manager.moc"
#endif
