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

#if __clang__
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif

#include "contact-manager.hpp"
#include <QStringList>
#include <QFile>

#ifndef Q_MOC_RUN
#include <ndn-cxx/util/crypto.hpp>
#include <ndn-cxx/util/io.hpp>
#include <ndn-cxx/security/sec-rule-relative.hpp>
#include <ndn-cxx/security/validator-regex.hpp>
#include "cryptopp.hpp"
#include <boost/asio.hpp>
#include <boost/tokenizer.hpp>
#include <boost/filesystem.hpp>
#include "logging.h"
#endif

namespace fs = boost::filesystem;

// INIT_LOGGER("chronos.ContactManager");

namespace chronos{

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

using ndn::Face;
using ndn::OBufferStream;
using ndn::IdentityCertificate;
using ndn::Validator;
using ndn::ValidatorRegex;
using ndn::SecRuleRelative;
using ndn::OnDataValidated;
using ndn::OnDataValidationFailed;
using ndn::OnInterestValidated;
using ndn::OnInterestValidationFailed;


ContactManager::ContactManager(Face& face,
                               QObject* parent)
  : QObject(parent)
  , m_face(face)
  , m_dnsListenerId(0)
{
  initializeSecurity();
}

ContactManager::~ContactManager()
{
}

// private methods
shared_ptr<IdentityCertificate>
ContactManager::loadTrustAnchor()
{
  shared_ptr<IdentityCertificate> anchor;

  QFile anchorFile(":/security/anchor.cert");

  if (!anchorFile.open(QIODevice::ReadOnly)) {
    emit warning(QString("Cannot load trust anchor!"));
    return anchor;
  }

  qint64 fileSize = anchorFile.size();
  char* buf = new char[fileSize];
  anchorFile.read(buf, fileSize);

  try {
    using namespace CryptoPP;

    OBufferStream os;
    StringSource(reinterpret_cast<const uint8_t*>(buf), fileSize, true,
                 new Base64Decoder(new FileSink(os)));
    anchor = make_shared<IdentityCertificate>();
    anchor->wireDecode(Block(os.buf()));
  }
  catch (CryptoPP::Exception& e) {
    emit warning(QString("Cannot load trust anchor!"));
  }
  catch (IdentityCertificate::Error& e) {
    emit warning(QString("Cannot load trust anchor!"));
  }
  catch(Block::Error& e) {
    emit warning(QString("Cannot load trust anchor!"));
  }

  delete [] buf;

  return anchor;
}

void
ContactManager::initializeSecurity()
{
  shared_ptr<IdentityCertificate> anchor = loadTrustAnchor();

  shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(boost::ref(m_face));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><ENDORSED>",
                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
                                                                  "==", "\\1", "\\1\\2", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><><ENDORSEE>",
                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
                                                                  "==", "\\1", "\\1\\2", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<DNS>]*)<DNS><PROFILE>",
                                                                  "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
                                                                  "==", "\\1", "\\1\\2", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
                                                                  "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$",
                                                                  "==", "\\1", "\\1\\2", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
                                                                  "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
                                                                  ">", "\\1\\2", "\\1", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
                                                                  "==", "\\1", "\\1\\2", true));
  validator->addDataVerificationRule(make_shared<SecRuleRelative>("^(<>*)$",
                                                                  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
                                                                  ">", "\\1", "\\1\\2", true));
  validator->addTrustAnchor(anchor);
  m_validator = validator;
}

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

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

  OnDataValidated onValidated =
    bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
  OnDataValidationFailed 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, int certIndex)
{
  shared_ptr<EndorseCollection> endorseCollection =
    m_bufferedContacts[identity].m_endorseCollection;

  if(certIndex >= endorseCollection->endorsement_size())
    prepareEndorseInfo(identity);

  Name interestName(endorseCollection->endorsement(certIndex).certname());

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

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

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

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

  map<string, int> endorseCount;
  for (Profile::const_iterator pIt = profile.begin(); pIt != profile.end(); pIt++) {
    // _LOG_DEBUG("prepareEndorseInfo: profile[" << pIt->first << "]: " << pIt->second);
    endorseCount[pIt->first] = 0;
  }

  int endorseCertCount = 0;

  vector<shared_ptr<EndorseCertificate> >::const_iterator cIt =
    m_bufferedContacts[identity].m_endorseCertList.begin();
  vector<shared_ptr<EndorseCertificate> >::const_iterator cEnd =
    m_bufferedContacts[identity].m_endorseCertList.end();

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

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

    if (!Validator::verifySignature(**cIt, contact->getPublicKey()))
      continue;

    const Profile& tmpProfile = (*cIt)->getProfile();
    if (tmpProfile != profile)
      continue;

    const vector<string>& endorseList = (*cIt)->getEndorseList();
    for (vector<string>::const_iterator eIt = endorseList.begin(); eIt != endorseList.end(); eIt++)
      endorseCount[*eIt] += 1;
  }

  for (Profile::const_iterator pIt = profile.begin(); pIt != profile.end(); pIt++) {
    Chronos::EndorseInfo::Endorsement* endorsement = endorseInfo->add_endorsement();
    endorsement->set_type(pIt->first);
    endorsement->set_value(pIt->second);
    std::stringstream ss;
    ss << endorseCount[pIt->first] << "/" << endorseCertCount;
    endorsement->set_endorse(ss.str());
  }

  emit contactEndorseInfoReady (*endorseInfo);
}

void
ContactManager::onDnsSelfEndorseCertValidated(const shared_ptr<const Data>& data,
                                              const Name& identity)
{
  try {
    Data plainData;
    plainData.wireDecode(data->getContent().blockFromValue());
    shared_ptr<EndorseCertificate> selfEndorseCertificate =
      make_shared<EndorseCertificate>(boost::cref(plainData));
    if (Validator::verifySignature(plainData, selfEndorseCertificate->getPublicKeyInfo())) {
      m_bufferedContacts[identity].m_selfEndorseCert = selfEndorseCertificate;
      fetchCollectEndorse(identity);
    }
    else
      emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
  }
  catch(Block::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
  }
  catch(Data::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
  }
  catch(EndorseCertificate::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
  }
}

void
ContactManager::onDnsSelfEndorseCertValidationFailed(const shared_ptr<const Data>& data,
                                                     const string& failInfo,
                                                     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 shared_ptr<const Data>& data,
                                             const Name& identity)
{
  shared_ptr<EndorseCollection> endorseCollection = make_shared<EndorseCollection>();
  if (!endorseCollection->ParseFromArray(data->getContent().value(),
                                         data->getContent().value_size())) {
    m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
    fetchEndorseCertificateInternal(identity, 0);
  }
  else
    prepareEndorseInfo(identity);
}

void
ContactManager::onDnsCollectEndorseValidationFailed(const shared_ptr<const Data>& data,
                                                    const string& failInfo,
                                                    const Name& identity)
{
  prepareEndorseInfo(identity);
}

void
ContactManager::onDnsCollectEndorseTimeoutNotify(const Interest& interest, const Name& identity)
{
  // _LOG_DEBUG("onDnsCollectEndorseTimeoutNotify: " << interest.getName());
  prepareEndorseInfo(identity);
}

void
ContactManager::onEndorseCertificateInternal(const Interest& interest, Data& data,
                                             const Name& identity, int certIndex, string hash)
{
  std::stringstream ss;
  {
    using namespace CryptoPP;

    SHA256 hash;
    StringSource(data.wireEncode().wire(), data.wireEncode().size(), true,
                 new HashFilter(hash, new FileSink(ss)));
  }

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

  fetchEndorseCertificateInternal(identity, certIndex+1);
}

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

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

    for (ContactList::iterator 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.setInterestLifetime(time::milliseconds(1000));

      OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
      OnDataValidationFailed onValidationFailed =
        bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1, _2);
      TimeoutNotify timeoutNotify = bind(&ContactManager::onDnsEndorseeTimeoutNotify, this, _1);

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

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

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

  decreaseCollectStatus();
}

void
ContactManager::onDnsEndorseeValidationFailed(const shared_ptr<const Data>& data,
                                              const string& failInfo)
{
  decreaseCollectStatus();
}

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

void
ContactManager::decreaseCollectStatus()
{
  int 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();

  shared_ptr<Data> data = make_shared<Data>();
  data->setName(dnsName);

  EndorseCollection endorseCollection;
  m_contactStorage->getCollectEndorse(endorseCollection);

  OBufferStream os;
  endorseCollection.SerializeToOstream(&os);

  data->setContent(os.buf());
  m_keyChain.signByIdentity(*data, m_identity);

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

void
ContactManager::onIdentityCertValidated(const shared_ptr<const Data>& data)
{
  shared_ptr<IdentityCertificate> cert = make_shared<IdentityCertificate>(boost::cref(*data));
  m_bufferedIdCerts[cert->getName()] = cert;
  decreaseIdCertCount();
}

void
ContactManager::onIdentityCertValidationFailed(const shared_ptr<const Data>& data,
                                               const string& failInfo)
{
  // _LOG_DEBUG("ContactManager::onIdentityCertValidationFailed " << data->getName());
  decreaseIdCertCount();
}

void
ContactManager::onIdentityCertTimeoutNotify(const Interest& interest)
{
  // _LOG_DEBUG("ContactManager::onIdentityCertTimeoutNotify: " << interest.getName());
  decreaseIdCertCount();
}

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

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

    for(BufferedIdCerts::const_iterator 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)
{
  Name certificateName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);

  shared_ptr<IdentityCertificate> signingCert = m_keyChain.getCertificate(certificateName);

  vector<string> endorseList;
  for (Profile::const_iterator it = profile.begin(); it != profile.end(); it++)
    endorseList.push_back(it->first);

  shared_ptr<EndorseCertificate> selfEndorseCertificate =
    make_shared<EndorseCertificate>(boost::cref(*signingCert),
                                    boost::cref(profile),
                                    boost::cref(endorseList));

  m_keyChain.sign(*selfEndorseCertificate, certificateName);

  return selfEndorseCertificate;
}

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

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

  m_keyChain.signByIdentity(*data, m_identity);

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

shared_ptr<EndorseCertificate>
ContactManager::generateEndorseCertificate(const Name& identity)
{
  shared_ptr<Contact> contact = getContact(identity);
  if (!static_cast<bool>(contact))
    return shared_ptr<EndorseCertificate>();

  Name signerKeyName = m_keyChain.getDefaultKeyNameForIdentity(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(),
                                                          signerKeyName,
                                                          contact->getProfile(),
                                                          endorseList));
  m_keyChain.signByIdentity(*cert, m_identity);
  return cert;

}

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

  shared_ptr<Data> data = make_shared<Data>();
  data->setName(dnsName);
  data->setContent(endorseCertificate.wireEncode());

  m_keyChain.signByIdentity(*data, m_identity);

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

void
ContactManager::sendInterest(const Interest& interest,
                             const OnDataValidated& onValidated,
                             const OnDataValidationFailed& 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));
}

void
ContactManager::onTargetData(const Interest& interest,
                             const Data& data,
                             const OnDataValidated& onValidated,
                             const OnDataValidationFailed& onValidationFailed)
{
  // _LOG_DEBUG("On receiving data: " << data.getName());
  m_validator->validate(data, onValidated, onValidationFailed);
}

void
ContactManager::onTargetTimeout(const Interest& interest,
                                int retry,
                                const OnDataValidated& onValidated,
                                const OnDataValidationFailed& onValidationFailed,
                                const TimeoutNotify& timeoutNotify)
{
  // _LOG_DEBUG("On interest timeout: " << interest.getName());
  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()));
}


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

  m_contactStorage = make_shared<ContactStorage>(m_identity);

  Name dnsPrefix;
  dnsPrefix.append(m_identity).append("DNS");
  const ndn::RegisteredPrefixId* dnsListenerId =
    m_face.setInterestFilter(dnsPrefix,
                             bind(&ContactManager::onDnsInterest,
                                  this, _1, _2),
                             bind(&ContactManager::onDnsRegisterFailed,
                                  this, _1, _2));

  if (m_dnsListenerId != 0)
    m_face.unsetInterestFilter(m_dnsListenerId);

  m_dnsListenerId = dnsListenerId;

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

  m_bufferedContacts.clear();

  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");

  // _LOG_DEBUG("onFetchContactInfo " << identity.toStdString() << " profile: " << interestName);

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

  OnDataValidated onValidated =
    bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
  OnDataValidationFailed 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)
{
  // _LOG_DEBUG("onAddFetchedContact");

  Name identityName(identity.toStdString());

  BufferedContacts::const_iterator it = m_bufferedContacts.find(identityName);
  if (it != m_bufferedContacts.end()) {
    Contact contact(*(it->second.m_selfEndorseCert));
    // _LOG_DEBUG("onAddFetchedContact: contact ready");
    try {
      m_contactStorage->addContact(contact);
      m_bufferedContacts.erase(identityName);

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

      onWaitForContactList();
    }
    catch(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;

  // _LOG_DEBUG("ContactManager::onUpdateProfile: getProfile");

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

  m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate);

  publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
}

void
ContactManager::onRefreshBrowseContact()
{
  vector<string> bufferedIdCertNames;
  try {
    using namespace boost::asio::ip;
    tcp::iostream request_stream;
    request_stream.expires_from_now(boost::posix_time::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;
    unsigned int 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(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 (vector<string>::const_iterator it = bufferedIdCertNames.begin();
       it != bufferedIdCertNames.end(); it++) {
    Name certName(*it);

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

    OnDataValidated onValidated =
    bind(&ContactManager::onIdentityCertValidated, this, _1);
    OnDataValidationFailed onValidationFailed =
    bind(&ContactManager::onIdentityCertValidationFailed, this, _1, _2);
    TimeoutNotify timeoutNotify =
    bind(&ContactManager::onIdentityCertTimeoutNotify, this, _1);

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

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 = IdentityCertificate::certificateNameToPublicKeyName(certName).getPrefix(-1);

  BufferedIdCerts::const_iterator 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(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 (ContactList::const_iterator 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 (ContactList::const_iterator 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<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identityName);

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

  m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identityName);

  publishEndorseCertificateInDNS(*newEndorseCertificate);
}

} // namespace chronos


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