/* -*- 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>

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

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

INIT_LOGGER("chronos.ContactManager");

namespace chronos{

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
void
ContactManager::initializeSecurity()
{
  fs::path anchorPath = fs::path(getenv("HOME")) / ".chronos" / "anchor.cert";
  shared_ptr<IdentityCertificate> anchor = io::load<IdentityCertificate>(anchorPath.c_str());

  shared_ptr<ValidatorRegex> validator = make_shared<ValidatorRegex>(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(1000);
  interest.setMustBeFresh(true);

  OnDataValidated onValidated = bind(&ContactManager::onDnsCollectEndorseValidated, this, _1, identity);
  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsCollectEndorseValidationFailed, this, _1, 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(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();

  map<string, int> endorseCount;
  for(; pIt != pEnd; 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();
      vector<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);
      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 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 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)
{
  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(1000);
        
        OnDataValidated onValidated = bind(&ContactManager::onDnsEndorseeValidated, this, _1);
        OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsEndorseeValidationFailed, this, _1);
        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)
{
  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)
{
  _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);

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

  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 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(1000);
  interest.setMustBeFresh(true);

  OnDataValidated onValidated = bind(&ContactManager::onDnsSelfEndorseCertValidated, this, _1, identityName);
  OnDataValidationFailed onValidationFailed = bind(&ContactManager::onDnsSelfEndorseCertValidationFailed, this, _1, 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()
{
  return; // the website info is not available.

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

      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;
        }
      vector<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(1000);
      interest.setMustBeFresh(true);
      
      OnDataValidated onValidated = bind(&ContactManager::onIdentityCertValidated, this, _1);
      OnDataValidationFailed onValidationFailed = bind(&ContactManager::onIdentityCertValidationFailed, this, _1);
      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
