/* -*- 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 push
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-function"
#elif __GNUC__
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#endif


#include "contact-manager.h"

#ifndef Q_MOC_RUN
#include <ndn-cpp/face.hpp>
#include <ndn-cpp/security/signature/signature-sha256-with-rsa.hpp>
#include <ndn-cpp/security/verifier.hpp>
#include <cryptopp/base64.h>
#include <ndn-cpp-et/policy-manager/identity-policy-rule.hpp>
#include <fstream>
#include "endorse-collection.pb.h"
#include "null-ptrs.h"
#include "logging.h"
#endif

using namespace ndn;
using namespace ndn::ptr_lib;
using namespace std;

INIT_LOGGER("ContactManager");

ContactManager::ContactManager(shared_ptr<KeyChain> keyChain, 
                               shared_ptr<Face> face,
                               QObject* parent)
  : QObject(parent),
    m_face(face)
{
  m_keyChain = keyChain;
  m_contactStorage = make_shared<ContactStorage>();
  m_dnsStorage = make_shared<DnsStorage>();

  initializeSecurity();
}

ContactManager::~ContactManager()
{}

void
ContactManager::initializeSecurity()
{
  m_policyManager = make_shared<SimplePolicyManager>();

  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^([^<DNS>]*)<DNS><ENDORSED>",
                                                                             "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
                                                                             "==", "\\1", "\\1\\2", true));
  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^([^<DNS>]*)<DNS><PROFILE>",
                                                                             "^([^<KEY>]*)<KEY>(<>*)[<ksk-.*><dsk-.*>]<ID-CERT>$",
                                                                             "==", "\\1", "\\1\\2", true));
  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
                                                                             "^([^<KEY>]*)<KEY>(<>*<ksk-.*>)<ID-CERT>$", 
                                                                             "==", "\\1", "\\1\\2", true));
  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>",
                                                                             "^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>$",
                                                                             ">", "\\1\\2", "\\1", true));
  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^([^<KEY>]*)<KEY><dsk-.*><ID-CERT>",
                                                                             "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
                                                                             "==", "\\1", "\\1\\2", true));
  m_policyManager->addVerificationPolicyRule(make_shared<IdentityPolicyRule>("^(<>*)$", 
                                                                             "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$", 
                                                                             ">", "\\1", "\\1\\2", true));
  

  m_policyManager->addSigningPolicyRule(make_shared<IdentityPolicyRule>("^([^<DNS>]*)<DNS><PROFILE>",
                                                                        "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
                                                                        "==", "\\1", "\\1\\2", true));


  const string TrustAnchor("BIICqgOyEIWlKzDI2xX2hdq5Azheu9IVyewcV4uM7ylfh67Y8MIxF3tDCTx5JgEn\
HYMuCaYQm6XuaXTlVfDdWff/K7Xebq8IgGxjNBeU9eMf7Gy9iIMrRAOdBG0dBHmo\
67biGs8F+P1oh1FwKu/FN1AE9vh8HSOJ94PWmjO+6PvITFIXuI3QbcCz8rhvbsfb\
5X/DmfbJ8n8c4X3nVxrBm6fd4z8kOFOvvhgJImvqsow69Uy+38m8gJrmrcWMoPBJ\
WsNLcEriZCt/Dlg7EqqVrIn6ukylKCvVrxA9vm/cEB74J/N+T0JyMRDnTLm17gpq\
Gd75rhj+bLmpOMOBT7Nb27wUKq8gcXzeAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
MzMyNTcyMAD6vUlELUNFUlQA+q39PgurHgAAAaID4gKF5vjua9EIr3/Fn8k1AdSc\
nEryjVDW3ikvYoSwjK7egTkAArq1BSc+C6sdAAHiAery+p1uZG4A+p1LRVkA+vVr\
c2stMTM4MzMyNTcyMAD6vUlELUNFUlQAAAAAAAGaFr0wggFjMCIYDzIwMTMxMTAx\
MTcxMTIyWhgPMjAxNDExMDExNzExMjJaMBkwFwYDVQQpExBORE4gVGVzdGJlZCBS\
b290MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA06x+elwzWCHa4I3b\
yrYCMAIVxQpRVLuOXp0h+BS+5GNgMVPi7+40o4zSJG+kiU8CIH1mtj8RQAzBX9hF\
I5VAyOC8nS8D8YOfBwt2yRDZPgt1E5PpyYUBiDYuq/zmJDL8xjxAlxrMzVOqD/uj\
/vkkcBM/T1t9Q6p1CpRyq+GMRbV4EAHvH7MFb6bDrH9t8DHEg7NPUCaSQBrd7PvL\
72P+QdiNH9zs/EiVzAkeMG4iniSXLuYM3z0gMqqcyUUUr6r1F9IBmDO+Kp97nZh8\
VCL+cnIEwyzAFAupQH5GoXUWGiee8oKWwH2vGHX7u6sWZsCp15NMSG3OC4jUIZOE\
iVUF1QIBEQAA");

  string decoded;
  CryptoPP::StringSource ss(reinterpret_cast<const unsigned char *>(TrustAnchor.c_str()), 
                            TrustAnchor.size(), 
                            true,
                            new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded)));
  Data data;
  data.wireDecode(Block(reinterpret_cast<const uint8_t*>(decoded.c_str()), decoded.size()));
  shared_ptr<IdentityCertificate> anchor = make_shared<IdentityCertificate>(data);
  m_policyManager->addTrustAnchor(anchor);  

#ifdef _DEBUG

  const string FakeAnchor("BIICqgOyEIVAaoHnQZIx5osAuY2fKte4HBSrxyam7MY6/kp+w47O1bGdd2KjeZKV\
zZzQd3EQorDC3KUPbB6ql30jYfspvo4OPSlIuDrkyROaoZ+MSKyzQYpB6CZcTjBa\
qcWYFOfwUlcWvkbd00X4bkc5PkcWpVdRrx+NCTiq9EXes//hOHpEJHMNsJUi45O+\
6M4OE6/sNEqs/ryHn2w1vCqwPpG8xzcd0prQUdCH2MGE77F+H0XFDuWp8mrT37Uw\
DUy7Ltm+7nDTHSQy2J3Zk4Q+0tjxCzSw4owEpwOHr+afdkuE3v9aB2NRQBBDCEmL\
Ykz4sYX3XE8MVFqRn1HHWCkszjDg+F0UAADy+p1uZG4A+p1LRVkA+vVrc2stMTM4\
MjkzNDE5OAD6vUlELUNFUlQA+s39/////95rc7MAAAGiA+IChaK1eVvzlkg6BJAw\
qiOpxRoezQ0hAHOBbPRLeBllxMN7AAK6tQUm3mtztQAB4gHq8vqdbmRuAPqdS0VZ\
APr1a3NrLTEzODI5MzQxOTgA+r1JRC1DRVJUAAAAAAABmhblMIIBaDAiGA8yMDEz\
MTAyODAwMDAwMFoYDzIwMzMxMDI4MDAwMDAwWjAcMBoGA1UEKRMTL25kbi9rc2st\
MTM4MjkzNDE5ODCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2htIFF\
/PH+SJsGOA6jhpFT74xfLJlgZNJOnKzl27HI2gupE0mainWj/HqVzdGxD6jOOReI\
sul+eQyEyBYq4e35pLmdJGlux/+UPQ51DD8jg04GrUPewV7+iGm6usp/7xEGHbah\
H2Grv/bsGrt6aRA8cKmdIc+rehxZCVFtiwSEHTnOWzn3lfZR5xnjF9aGX+uGo1hA\
gMwu1ECxg4H3O4z1tbTzji5+WH0RDsPRlgzQX6wAQH8btlQyoFJfljEA3QaOtDaB\
OcfegIlClzutmgJnK9i5ZLz2Mjvx49dlCWAVKg65vOXMLC/33jD9F+V8urwsBlOb\
F7Wh5ayeo8NBKDsCAwEAAQAA");

  string decoded2;
  CryptoPP::StringSource ss2(reinterpret_cast<const unsigned char *>(FakeAnchor.c_str()), 
                            FakeAnchor.size(), 
                            true,
                            new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded2)));
  Data data2;
  data2.wireDecode(Block(reinterpret_cast<const uint8_t*>(decoded.c_str()), decoded.size()));
  shared_ptr<IdentityCertificate>anchor2 = make_shared<IdentityCertificate>(data2);
  m_policyManager->addTrustAnchor(anchor2);  

#endif
}


void
ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
{
  Name interestName = identity;
  interestName.append("DNS").append("PROFILE");
  
  Interest interest(interestName);

  OnVerified onVerified = func_lib::bind(&ContactManager::onDnsSelfEndorseCertificateVerified, this, _1, identity);
  OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactManager::onDnsSelfEndorseCertificateVerifyFailed, this, _1, identity);
  TimeoutNotify timeoutNotify = func_lib::bind(&ContactManager::onDnsSelfEndorseCertificateTimeoutNotify, this, identity);

  sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify);
}

void
ContactManager::onDnsSelfEndorseCertificateTimeoutNotify(const Name& identity)
{ emit contactFetchFailed(identity); }

void
ContactManager::onDnsSelfEndorseCertificateVerified(const shared_ptr<Data>& data, 
                                                    const Name& identity)
{
  try{
    Data plainData;
    plainData.wireDecode(Block(data->getContent().value(), data->getContent().value_size()));
    EndorseCertificate selfEndorseCertificate(plainData);
    if(Verifier::verifySignature(plainData, plainData.getSignature(), selfEndorseCertificate.getPublicKeyInfo()))
      emit contactFetched (selfEndorseCertificate); 
    else
      emit contactFetchFailed (identity);
  }catch(std::exception& e){
    _LOG_ERROR("Exception: " << e.what());
    emit contactFetchFailed (identity);
  }
}

void
ContactManager::onDnsSelfEndorseCertificateVerifyFailed(const shared_ptr<Data>& data, 
                                                        const Name& identity)
{ emit contactFetchFailed (identity); }

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

  Interest interest(interestName);
  interest.setInterestLifetime(1000);

  OnVerified onVerified = func_lib::bind(&ContactManager::onDnsCollectEndorseVerified, this, _1, identity);
  OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactManager::onDnsCollectEndorseVerifyFailed, this, _1, identity);
  TimeoutNotify timeoutNotify = func_lib::bind(&ContactManager::onDnsCollectEndorseTimeoutNotify, this, identity);

  sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify);
}

void
ContactManager::onDnsCollectEndorseTimeoutNotify(const Name& identity)
{
  emit collectEndorseFetchFailed (identity);
}

void
ContactManager::onDnsCollectEndorseVerified(const shared_ptr<Data>& data, const Name& identity)
{ emit collectEndorseFetched (*data); }

void
ContactManager::onDnsCollectEndorseVerifyFailed(const shared_ptr<Data>& data, const Name& identity)
{ emit collectEndorseFetchFailed (identity); }


void
ContactManager::fetchKey(const ndn::Name& certName)
{
  Name interestName = certName;
  
  Interest interest(interestName);
  interest.setInterestLifetime(1000);

  OnVerified onVerified = func_lib::bind(&ContactManager::onKeyVerified, this, _1, certName);
  OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactManager::onKeyVerifyFailed, this, _1, certName);
  TimeoutNotify timeoutNotify = func_lib::bind(&ContactManager::onKeyTimeoutNotify, this, certName);

  sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify);
}


void
ContactManager::onKeyVerified(const shared_ptr<Data>& data, const Name& identity)
{
  IdentityCertificate identityCertificate(*data);

  Profile profile(identityCertificate);
  ProfileData profileData(profile);

  Name certificateName = m_keyChain->getDefaultCertificateName();
  m_keyChain->sign(profileData, certificateName);

  try{
    EndorseCertificate endorseCertificate(identityCertificate, profileData);
    m_keyChain->sign(endorseCertificate, certificateName);
    emit contactKeyFetched (endorseCertificate); 
  }catch(std::exception& e){
    _LOG_ERROR("Exception: " << e.what());
    return;
  }
}

void
ContactManager::onKeyVerifyFailed(const shared_ptr<Data>& data, const Name& identity)
{ 
  _LOG_DEBUG("Key cannot be verified!");
  emit contactKeyFetchFailed (identity); 
}

void
ContactManager::onKeyTimeoutNotify(const Name& identity)
{ 
  _LOG_DEBUG("Key timeout!");
  emit contactKeyFetchFailed(identity); 
}

void
ContactManager::fetchIdCertificate(const Name& certName)
{
  Name interestName = certName;
  
  Interest interest(interestName);
  interest.setInterestLifetime(1000);

  OnVerified onVerified = boost::bind(&ContactManager::onIdCertificateVerified, this, _1, certName);
  OnVerifyFailed onVerifyFailed = boost::bind(&ContactManager::onIdCertificateVerifyFailed, this, _1, certName);
  TimeoutNotify timeoutNotify = boost::bind(&ContactManager::onIdCertificateTimeoutNotify, this, certName);

  sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify);
}

void
ContactManager::onIdCertificateTimeoutNotify(const Name& identity)
{ 
  emit contactCertificateFetchFailed (identity); 
}


void
ContactManager::onIdCertificateVerified(const shared_ptr<Data>& data, const Name& identity)
{
  IdentityCertificate identityCertificate(*data);
  emit contactCertificateFetched(identityCertificate);
}

void
ContactManager::onIdCertificateVerifyFailed(const shared_ptr<Data>& data, const Name& identity)
{ 
  emit contactCertificateFetchFailed (identity); 
}

void
ContactManager::onTargetData(const shared_ptr<const ndn::Interest>& interest, 
                             const shared_ptr<Data>& data,
                             int stepCount,
                             const OnVerified& onVerified,
                             const OnVerifyFailed& onVerifyFailed,
                             const TimeoutNotify& timeoutNotify)
{
  shared_ptr<ValidationRequest> nextStep = m_policyManager->checkVerificationPolicy(data, stepCount, onVerified, onVerifyFailed);

  if (nextStep)
    m_face->expressInterest
      (*nextStep->interest_, 
       bind(&ContactManager::onCertData, this, _1, _2, nextStep), 
       bind(&ContactManager::onCertTimeout, this, _1, onVerifyFailed, data, nextStep));

}

void
ContactManager::onTargetTimeout(const shared_ptr<const ndn::Interest>& interest, 
                                int retry,
                                int stepCount,
                                const OnVerified& onVerified,
                                const OnVerifyFailed& onVerifyFailed,
                                const TimeoutNotify& timeoutNotify)
{
  if(retry > 0)
    sendInterest(*interest, onVerified, onVerifyFailed, timeoutNotify, retry-1, stepCount);
  else
    {
      _LOG_DEBUG("Interest: " << interest->getName().toUri() << " eventually times out!");
      timeoutNotify();
    }
}

void
ContactManager::onCertData(const shared_ptr<const ndn::Interest>& interest, 
                           const shared_ptr<Data>& cert,
                           shared_ptr<ValidationRequest> previousStep)
{
  shared_ptr<ValidationRequest> nextStep = m_policyManager->checkVerificationPolicy(cert, 
                                                                                    previousStep->stepCount_, 
                                                                                    previousStep->onVerified_, 
                                                                                    previousStep->onVerifyFailed_);

  if (nextStep)
    m_face->expressInterest
      (*nextStep->interest_, 
       bind(&ContactManager::onCertData, this, _1, _2, nextStep), 
       bind(&ContactManager::onCertTimeout, this, _1, previousStep->onVerifyFailed_, cert, nextStep));
}

void
ContactManager::onCertTimeout(const shared_ptr<const ndn::Interest>& interest,
                              const OnVerifyFailed& onVerifyFailed,
                              const shared_ptr<Data>& data,
                              shared_ptr<ValidationRequest> nextStep)
{
  if(nextStep->retry_ > 0)
    m_face->expressInterest(*interest, 
                            bind(&ContactManager::onCertData,
                                 this,
                                 _1,
                                 _2,
                                 nextStep),
                            bind(&ContactManager::onCertTimeout,
                                 this,
                                 _1,
                                 onVerifyFailed,
                                 data,
                                 nextStep));
 else
   onVerifyFailed(data);
}

void
ContactManager::sendInterest(const Interest& interest,
                             const OnVerified& onVerified,
                             const OnVerifyFailed& onVerifyFailed,
                             const TimeoutNotify& timeoutNotify,
                             int retry /* = 1 */,
                             int stepCount /* = 0 */)
{
  uint64_t id = m_face->expressInterest(interest, 
                          boost::bind(&ContactManager::onTargetData, 
                                      this,
                                      _1,
                                      _2,
                                      stepCount,
                                      onVerified, 
                                      onVerifyFailed,
                                      timeoutNotify),
                          boost::bind(&ContactManager::onTargetTimeout,
                                      this,
                                      _1,
                                      retry,
                                      stepCount,
                                      onVerified,
                                      onVerifyFailed,
                                      timeoutNotify));

  // _LOG_DEBUG("id: " << id << " entry id: " << m_face->getNode().getEntryIndexForExpressedInterest(interest.getName()));
}

void
ContactManager::updateProfileData(const Name& identity)
{
  // Get current profile;
  shared_ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
  if(CHRONOCHAT_NULL_PROFILE_PTR == newProfile)
    return;

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

  if(CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR == newEndorseCertificate)
    return;

  // Check if profile exists
  try{
    Block profileDataBlob = m_contactStorage->getSelfEndorseCertificate(identity);
    m_contactStorage->updateSelfEndorseCertificate(*newEndorseCertificate, identity);
  }catch(ContactStorage::Error &e){
    m_contactStorage->addSelfEndorseCertificate(*newEndorseCertificate, identity);
  }

  publishSelfEndorseCertificateInDNS(*newEndorseCertificate);
}

void
ContactManager::updateEndorseCertificate(const ndn::Name& identity, const ndn::Name& signerIdentity)
{
  shared_ptr<EndorseCertificate> newEndorseCertificate = generateEndorseCertificate(identity, signerIdentity);

  if(CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR == newEndorseCertificate)
    return;

  try{
    Block oldEndorseCertificateBlob = m_contactStorage->getEndorseCertificate(identity);
    m_contactStorage->updateEndorseCertificate(*newEndorseCertificate, identity);
  }catch(ContactStorage::Error &e){
    m_contactStorage->addEndorseCertificate(*newEndorseCertificate, identity);
  }

  publishEndorseCertificateInDNS(*newEndorseCertificate, signerIdentity);
}

shared_ptr<EndorseCertificate> 
ContactManager::generateEndorseCertificate(const Name& identity, const Name& signerIdentity)
{
  shared_ptr<ContactItem> contact = getContact(identity);
  if(contact == CHRONOCHAT_NULL_CONTACTITEM_PTR)
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;

  Name signerKeyName = m_keyChain->getDefaultKeyNameForIdentity(signerIdentity);
  Name signerCertName = m_keyChain->getDefaultCertificateNameForIdentity(signerIdentity);

  vector<string> endorseList;
  m_contactStorage->getEndorseList(identity, endorseList);

  
  try{
    shared_ptr<EndorseCertificate> cert = make_shared<EndorseCertificate>(contact->getSelfEndorseCertificate(), signerKeyName, endorseList); 
    m_keyChain->sign(*cert, signerCertName);
    return cert;
  }catch(std::exception& e){
    _LOG_ERROR("Exception: " << e.what());
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;
  } 
}

void
ContactManager::getContactItemList(vector<shared_ptr<ContactItem> >& contacts)
{ return m_contactStorage->getAllContacts(contacts); }

shared_ptr<ContactItem>
ContactManager::getContact(const ndn::Name& contactNamespace)
{ return m_contactStorage->getContact(contactNamespace); }

shared_ptr<EndorseCertificate>
ContactManager::getSignedSelfEndorseCertificate(const Name& identity,
                                                const Profile& profile)
{
  Name certificateName = m_keyChain->getDefaultCertificateNameForIdentity(identity);
  if(0 == certificateName.size())
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;

  ProfileData profileData(profile);
  m_keyChain->sign(profileData, certificateName);

  shared_ptr<IdentityCertificate> signingCert = m_keyChain->getCertificate(certificateName);
  if(CHRONOCHAT_NULL_IDENTITYCERTIFICATE_PTR == signingCert)
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;

  Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(signingCert->getName());

  shared_ptr<IdentityCertificate> kskCert;
  if(signingKeyName.get(-1).toEscapedString().substr(0,4) == string("dsk-"))
    {
      SignatureSha256WithRsa dskCertSig(signingCert->getSignature());
      // HACK! KSK certificate should be retrieved from network.
      Name keyName = IdentityCertificate::certificateNameToPublicKeyName(dskCertSig.getKeyLocator().getName());

      // TODO: check null existing cases.
      Name kskCertName = m_keyChain->getDefaultCertificateNameForIdentity(keyName.getPrefix(-1));

      kskCert = m_keyChain->getCertificate(kskCertName);
    }
  else
    {
      kskCert = signingCert;
    }

  if(CHRONOCHAT_NULL_IDENTITYCERTIFICATE_PTR == kskCert)
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;

  vector<string> endorseList;
  Profile::const_iterator it = profile.begin();
  for(; it != profile.end(); it++)
    endorseList.push_back(it->first);
  
  try{
    shared_ptr<EndorseCertificate> selfEndorseCertificate = make_shared<EndorseCertificate>(*kskCert, profileData, endorseList);
    m_keyChain->sign(*selfEndorseCertificate, kskCert->getName());

    return selfEndorseCertificate;
  }catch(std::exception& e){
    _LOG_ERROR("Exception: " << e.what());
    return CHRONOCHAT_NULL_ENDORSECERTIFICATE_PTR;
  } 
}


void
ContactManager::publishSelfEndorseCertificateInDNS(const EndorseCertificate& selfEndorseCertificate)
{
  Data data;

  Name keyName = selfEndorseCertificate.getPublicKeyName();
  Name identity = keyName.getSubName(0, keyName.size()-1);

  time_t nowSeconds = time(NULL);
  struct tm current = *gmtime(&nowSeconds);
  MillisecondsSince1970 version = timegm(&current) * 1000.0;

  Name dnsName = identity;
  dnsName.append("DNS").append("PROFILE").appendVersion(version);
  data.setName(dnsName);

  data.setContent(selfEndorseCertificate.wireEncode());

  Name signCertName = m_keyChain->getDefaultCertificateNameForIdentity(identity);
  m_keyChain->sign(data, signCertName);

  m_dnsStorage->updateDnsSelfProfileData(data, identity);
  
  m_face->put(data);
}

void
ContactManager::publishEndorseCertificateInDNS(const EndorseCertificate& endorseCertificate, const Name& signerIdentity)
{
  Data data;

  Name keyName = endorseCertificate.getPublicKeyName();
  Name endorsee = keyName.getSubName(0, keyName.size()-1);

  time_t nowSeconds = time(NULL);
  struct tm current = *gmtime(&nowSeconds);
  MillisecondsSince1970 version = timegm(&current) * 1000.0;

  Name dnsName = signerIdentity;
  dnsName.append("DNS").append(endorsee).append("ENDORSEE").appendVersion(version);
  data.setName(dnsName);

  data.setContent(endorseCertificate.wireEncode());

  Name signCertName = m_keyChain->getDefaultCertificateNameForIdentity(signerIdentity);
  m_keyChain->sign(data, signCertName);

  m_dnsStorage->updateDnsEndorseOthers(data, signerIdentity, endorsee);

  m_face->put(data);
}

void
ContactManager::publishEndorsedDataInDns(const Name& identity)
{
  Data data;

  time_t nowSeconds = time(NULL);
  struct tm current = *gmtime(&nowSeconds);
  MillisecondsSince1970 version = timegm(&current) * 1000.0;

  Name dnsName = identity;
  dnsName.append("DNS").append("ENDORSED").appendVersion(version);
  data.setName(dnsName);
  
  vector<Buffer> collectEndorseList;
  m_contactStorage->getCollectEndorseList(identity, collectEndorseList);
  
  Chronos::EndorseCollection endorseCollection;

  vector<Buffer>::const_iterator it = collectEndorseList.begin();
  for(; it != collectEndorseList.end(); it++)
    {
      string entryStr(reinterpret_cast<const char*>(it->buf()), it->size());
      endorseCollection.add_endorsement()->set_blob(entryStr);
    }

  string encoded;
  endorseCollection.SerializeToString(&encoded);

  data.setContent(reinterpret_cast<const uint8_t*>(encoded.c_str()), encoded.size());
  
  Name signCertName = m_keyChain->getDefaultCertificateNameForIdentity(identity);
  m_keyChain->sign(data, signCertName);

  m_dnsStorage->updateDnsOthersEndorse(data, identity);

  m_face->put(data);
}

void
ContactManager::addContact(const IdentityCertificate& identityCertificate, const Profile& profile)
{
  ProfileData profileData(profile);
  
  Name certificateName = m_keyChain->getDefaultCertificateNameForIdentity (m_defaultIdentity);
  m_keyChain->sign(profileData, certificateName);


  try{
    EndorseCertificate endorseCertificate(identityCertificate, profileData);
    
    m_keyChain->sign(endorseCertificate, certificateName);

    ContactItem contactItem(endorseCertificate);

    m_contactStorage->addContact(contactItem);

    emit contactAdded(contactItem.getNameSpace());

  }catch(std::exception& e){
    emit warning(e.what());
    _LOG_ERROR("Exception: " << e.what());
    return;
  }
}

void
ContactManager::removeContact(const ndn::Name& contactNameSpace)
{
  shared_ptr<ContactItem> contact = getContact(contactNameSpace);
  if(contact == CHRONOCHAT_NULL_CONTACTITEM_PTR)
    return;
  m_contactStorage->removeContact(contactNameSpace);
  emit contactRemoved(contact->getPublicKeyName());
}


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