/* -*- 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.h"
#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/base64.h>
#include <cryptopp/files.h>
#include <cryptopp/sha.h>
#include <cryptopp/filters.h>
#include <boost/asio.hpp>
#include <boost/tokenizer.hpp>
#include <boost/filesystem.hpp>
#include "logging.h"
#endif

using namespace ndn;
namespace fs = boost::filesystem;

INIT_LOGGER("chronos.ContactManager");

namespace chronos{

using ndn::shared_ptr;

static const uint8_t DNS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.

ContactManager::ContactManager(shared_ptr<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<EndorseInfo> endorseInfo = make_shared<EndorseInfo>();
  m_bufferedContacts[identity].m_endorseInfo = endorseInfo;

  Profile::const_iterator pIt  = profile.begin();
  Profile::const_iterator pEnd = profile.end();

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

  int endorseCertCount = 0;

  std::vector<shared_ptr<EndorseCertificate> >::const_iterator cIt  = m_bufferedContacts[identity].m_endorseCertList.begin();
  std::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 std::vector<std::string>& endorseList = (*cIt)->getEndorseList();
      std::vector<std::string>::const_iterator eIt = endorseList.begin();
      for(; eIt != endorseList.end(); eIt++)
        endorseCount[*eIt] += 1;
    }

  pIt  = profile.begin();
  pEnd = profile.end();
  for(; pIt != pEnd; pIt++)
    {
      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 std::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 std::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,
                                             std::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();

    ContactList::iterator it  = m_contactList.begin();
    ContactList::iterator end = m_contactList.end();

    for(; it != 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 std::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();

  Data 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 std::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;

      BufferedIdCerts::const_iterator it  = m_bufferedIdCerts.begin();
      BufferedIdCerts::const_iterator end = m_bufferedIdCerts.end();
      for(; it != 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);

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

  shared_ptr<EndorseCertificate> selfEndorseCertificate =
    shared_ptr<EndorseCertificate>(new EndorseCertificate(*signingCert, profile, endorseList));

  m_keyChain.sign(*selfEndorseCertificate, certificateName);

  return selfEndorseCertificate;
}

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

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

  std::vector<std::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();

  Data data;
  data.setName(dnsName);
  data.setContent(endorseCertificate.wireEncode());

  m_keyChain.signByIdentity(data, m_identity);

  m_contactStorage->updateDnsEndorseOthers(data, dnsName.get(-3).toEscapedString());
  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()).toEscapedString());
      if(static_cast<bool>(data))
        m_face->put(*data);
      return;
    }

  if(interestName.size() == (prefix.size()+2))
    {
      data = m_contactStorage->getDnsData(interestName.get(prefix.size()).toEscapedString(),
                                          interestName.get(prefix.size()+1).toEscapedString());
      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);

  if(m_dnsListenerId)
    m_face->unsetInterestFilter(m_dnsListenerId);

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

  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()
{
  std::vector<std::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();

      std::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);
      std::string http_version;
      response_stream >> http_version;
      unsigned int status_code;
      response_stream >> status_code;
      std::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;
        }
      std::vector<std::string> headers;
      std::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();

  std::vector<std::string>::const_iterator it  = bufferedIdCertNames.begin();
  std::vector<std::string>::const_iterator end = bufferedIdCertNames.end();
  for(; it != 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()
{
  ContactList::const_iterator it  = m_contactList.begin();
  ContactList::const_iterator end = m_contactList.end();

  QStringList aliasList;
  QStringList idList;
  for(; it != 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)
{
  ContactList::const_iterator it  = m_contactList.begin();
  ContactList::const_iterator end = m_contactList.end();

  for(; it != 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
