/* -*- 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>
 *         Qiuhan Ding <qiuhanding@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("chronochat.ContactManager");

namespace chronochat {

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, size_t certIndex)
{
  shared_ptr<EndorseCollection> endorseCollection =
    m_bufferedContacts[identity].m_endorseCollection;

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

  Name interestName(endorseCollection->getCollectionEntries()[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->getCollectionEntries()[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<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
  m_bufferedContacts[identity].m_endorseInfo = endorseInfo;

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

  size_t 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++) {
    std::stringstream ss;
    ss << endorseCount[pIt->first] << "/" << endorseCertCount;
    endorseInfo->addEndorsement(pIt->first, pIt->second, 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(EndorseCertificate::Error& e) {
    emit contactInfoFetchFailed(QString::fromStdString(identity.toUri()));
  }
  catch(Data::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)
{
  try {
    shared_ptr<EndorseCollection> endorseCollection =
      make_shared<EndorseCollection>(data->getContent());
    m_bufferedContacts[identity].m_endorseCollection = endorseCollection;
    fetchEndorseCertificateInternal(identity, 0);
  }
  catch (tlv::Error) {
    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, size_t 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,
                                                    size_t 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()
{
  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();

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

  EndorseCollection endorseCollection;
  m_contactStorage->getCollectEndorse(endorseCollection);

  data->setContent(endorseCollection.wireEncode());
  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()
{
  size_t 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;
    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(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 chronochat


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