/* -*- 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("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, 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<chronochat::EndorseInfo> endorseInfo = make_shared<chronochat::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++) {
    chronochat::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(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)
{
  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 chronochat


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