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

#include "contactpanel.h"
#include "ui_contactpanel.h"


#include <QStringList>
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QDir>
#include <QtSql/QSqlRecord>
#include <QtSql/QSqlField>
#include <QtSql/QSqlError>

#ifndef Q_MOC_RUN
#include <ndn-cpp/security/verifier.hpp>
#include <ndn-cpp/security/signature-sha256-with-rsa.hpp>
#include <boost/filesystem.hpp>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include "logging.h"
#endif

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

using namespace std;

INIT_LOGGER("ContactPanel");

Q_DECLARE_METATYPE(ndn::IdentityCertificate)
Q_DECLARE_METATYPE(ChronosInvitation)

ContactPanel::ContactPanel(QWidget *parent) 
  : QDialog(parent)
  , ui(new Ui::ContactPanel)
  , m_warningDialog(new WarningDialog)
  , m_contactListModel(new QStringListModel)
  , m_startChatDialog(new StartChatDialog)
  , m_invitationDialog(new InvitationDialog)
  , m_settingDialog(new SettingDialog)
  , m_policy(new SecPolicyChronoChatPanel())
{
  qRegisterMetaType<IdentityCertificate>("IdentityCertificate");
  qRegisterMetaType<ChronosInvitation>("ChronosInvitation");

  startFace();  

  createAction();

  m_keyChain = make_shared<KeyChain>();

  m_contactManager = make_shared<ContactManager>(m_keyChain, m_face);

  connect(&*m_contactManager, SIGNAL(noNdnConnection(const QString&)),
          this, SLOT(showError(const QString&)));
  
  openDB();    

  refreshContactList();

  loadTrustAnchor();

  m_defaultIdentity = m_keyChain->getDefaultIdentity();
  if(m_defaultIdentity.size() == 0)
    showError(QString::fromStdString("certificate of ") + QString::fromStdString(m_defaultIdentity.toUri()) + " is missing!\nHave you installed the certificate?");
  Name defaultCertName = m_keyChain->getDefaultCertificateNameForIdentity(m_defaultIdentity);
  if(defaultCertName.size() == 0)
    showError(QString::fromStdString("certificate of ") + QString::fromStdString(m_defaultIdentity.toUri()) + " is missing!\nHave you installed the certificate?");


  m_contactManager->setDefaultIdentity(m_defaultIdentity);
  m_nickName = m_defaultIdentity.get(-1).toEscapedString();
  m_settingDialog->setIdentity(m_defaultIdentity.toUri(), m_nickName);
  

  m_profileEditor = new ProfileEditor(m_contactManager);
  m_profileEditor->setCurrentIdentity(m_defaultIdentity);

  m_addContactPanel = new AddContactPanel(m_contactManager);
  m_browseContactDialog = new BrowseContactDialog(m_contactManager);
  m_setAliasDialog = new SetAliasDialog(m_contactManager);
 
  ui->setupUi(this);

  
  m_localPrefix = Name("/private/local");
  setLocalPrefix();
    
  setInvitationListener();

  collectEndorsement();
  
  ui->ContactList->setModel(m_contactListModel);
  

  connect(ui->ContactList->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
          this, SLOT(updateSelection(const QItemSelection &, const QItemSelection &)));

  connect(ui->ContactList, SIGNAL(customContextMenuRequested(const QPoint&)),
          this, SLOT(showContextMenu(const QPoint&)));

  connect(ui->EditProfileButton, SIGNAL(clicked()), 
          this, SLOT(openProfileEditor()));

  connect(m_profileEditor, SIGNAL(noKeyOrCert(const QString&)),
          this, SLOT(showWarning(const QString&)));

  connect(ui->AddContactButton, SIGNAL(clicked()),
          this, SLOT(openBrowseContactDialog()));

  connect(m_browseContactDialog, SIGNAL(directAddClicked()),
          this, SLOT(openAddContactPanel()));

  connect(this, SIGNAL(refreshCertDirectory()),
          m_browseContactDialog, SLOT(refreshList()));

  connect(ui->DeleteContactButton, SIGNAL(clicked()),
          this, SLOT(removeContactButton()));
   
  connect(ui->settingButton, SIGNAL(clicked()),
          this, SLOT(openSettingDialog()));
   
  connect(m_addContactPanel, SIGNAL(newContactAdded()),
          this, SLOT(refreshContactList()));
  connect(m_browseContactDialog, SIGNAL(newContactAdded()),
          this, SLOT(refreshContactList()));
  connect(m_setAliasDialog, SIGNAL(aliasChanged()),
          this, SLOT(refreshContactList()));

  connect(m_startChatDialog, SIGNAL(chatroomConfirmed(const QString&, const QString&, bool)),
          this, SLOT(startChatroom(const QString&, const QString&, bool)));

  connect(m_invitationDialog, SIGNAL(invitationAccepted(const ChronosInvitation&, const ndn::IdentityCertificate&)),
          this, SLOT(acceptInvitation(const ChronosInvitation&, const ndn::IdentityCertificate&)));
  connect(m_invitationDialog, SIGNAL(invitationRejected(const ChronosInvitation&)),
          this, SLOT(rejectInvitation(const ChronosInvitation&)));
  
  connect(&*m_contactManager, SIGNAL(contactAdded(const ndn::Name&)),
          this, SLOT(addContactIntoPanelPolicy(const ndn::Name&)));
  connect(&*m_contactManager, SIGNAL(contactRemoved(const ndn::Name&)),
          this, SLOT(removeContactFromPanelPolicy(const ndn::Name&)));

  connect(m_settingDialog, SIGNAL(identitySet(const QString&, const QString&)),
          this, SLOT(updateDefaultIdentity(const QString&, const QString&)));

  connect(this, SIGNAL(newInvitationReady()),
          this, SLOT(openInvitationDialog()));

  connect(ui->isIntroducer, SIGNAL(stateChanged(int)),
          this, SLOT(isIntroducerChanged(int)));

  connect(ui->addScope, SIGNAL(clicked()),
          this, SLOT(addScopeClicked()));
  connect(ui->deleteScope, SIGNAL(clicked()),
          this, SLOT(deleteScopeClicked()));
  connect(ui->saveButton, SIGNAL(clicked()),
          this, SLOT(saveScopeClicked()));

  connect(ui->endorseButton, SIGNAL(clicked()),
          this, SLOT(endorseButtonClicked()));
}

ContactPanel::~ContactPanel()
{
  delete ui;
  delete m_contactListModel;
  delete m_startChatDialog;
  delete m_invitationDialog;
  delete m_settingDialog;

  delete m_profileEditor;
  delete m_addContactPanel;
  delete m_browseContactDialog;
  delete m_setAliasDialog;

  delete m_trustScopeModel;
  delete m_endorseDataModel;
  delete m_endorseComboBoxDelegate;

  delete m_menuInvite;
  delete m_menuAlias;

  map<Name, ChatDialog*>::iterator it = m_chatDialogs.begin();
  for(; it != m_chatDialogs.end(); it++)
    delete it->second;

  shutdownFace();
}

void
ContactPanel::startFace()
{
  m_face = make_shared<Face>();
  
  connectToDaemon();

  m_running = true;
  m_thread = boost::thread (&ContactPanel::eventLoop, this);  
}

void
ContactPanel::shutdownFace()
{
  {
    boost::unique_lock<boost::recursive_mutex> lock(m_mutex);
    m_running = false;
  }
  
  m_thread.join();
  m_face->shutdown();
}

void
ContactPanel::eventLoop()
{
  while (m_running)
    {
      try{
        m_face->processEvents();
        usleep(100);
      }catch(std::exception& e){
        _LOG_DEBUG(" " << e.what() );
      }
    }
}

void
ContactPanel::connectToDaemon()
{
  //Hack! transport does not connect to daemon unless an interest is expressed.
  Name name("/ndn");
  ndn::Interest interest(name);
  m_face->expressInterest(interest, 
                          func_lib::bind(&ContactPanel::onConnectionData, this, _1, _2),
                          func_lib::bind(&ContactPanel::onConnectionDataTimeout, this, _1));
}

void
ContactPanel::onConnectionData(const shared_ptr<const ndn::Interest>& interest,
                               const shared_ptr<Data>& data)
{ _LOG_DEBUG("onConnectionData"); }

void
ContactPanel::onConnectionDataTimeout(const shared_ptr<const ndn::Interest>& interest)
{ _LOG_DEBUG("onConnectionDataTimeout"); }

void
ContactPanel::createAction()
{
  m_menuInvite = new QAction("&Chat", this);
  m_menuAlias = new QAction("&Set Alias", this);
}

void
ContactPanel::openDB()
{
  QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  QString path = (QDir::home().path());
  path.append(QDir::separator()).append(".chronos").append(QDir::separator()).append("chronos.db");
  db.setDatabaseName(path);
  bool ok = db.open();
  _LOG_DEBUG("DB opened: " << std::boolalpha << ok );

  m_trustScopeModel = new QSqlTableModel;
  m_endorseDataModel = new QSqlTableModel;
  m_endorseComboBoxDelegate = new EndorseComboBoxDelegate;
}

void 
ContactPanel::loadTrustAnchor()
{
  vector<shared_ptr<ContactItem> >::const_iterator it = m_contactList.begin();
  for(; it != m_contactList.end(); it++)
    {
      _LOG_DEBUG("load contact: " << (*it)->getNameSpace().toUri());
      m_policy->addTrustAnchor((*it)->getSelfEndorseCertificate());
    }
}

void
ContactPanel::setLocalPrefix(int retry)
{
  Name interestName("/local/ndn/prefix");
  Interest interest(interestName);

  m_face->expressInterest(interest, 
                          func_lib::bind(&ContactPanel::onLocalPrefix, this, _1, _2), 
                          func_lib::bind(&ContactPanel::onLocalPrefixTimeout, this, _1, 10));
  
}

void
ContactPanel::onLocalPrefix(const shared_ptr<const Interest>& interest, 
                            const shared_ptr<Data>& data)
{
  string originPrefix((const char*)data->getContent().value(), data->getContent().value_size());
  string prefix = QString::fromStdString (originPrefix).trimmed ().toUtf8().constData();
  string randomSuffix = getRandomString();
  m_localPrefix = Name(prefix);
  
}

void
ContactPanel::onLocalPrefixTimeout(const shared_ptr<const Interest>& interest,
                                   int retry)
{ 
  if(retry > 0)
    {
      setLocalPrefix(retry - 1);
      return;
    }
  else{
    m_localPrefix = Name("/private/local");
  }
}

void
ContactPanel::setInvitationListener()
{
  m_inviteListenPrefix = Name("/ndn/broadcast/chronos/invitation");
  m_inviteListenPrefix.append(m_defaultIdentity);
  _LOG_DEBUG("Listening for invitation on prefix: " << m_inviteListenPrefix.toUri());
  m_invitationListenerId = m_face->setInterestFilter(m_inviteListenPrefix, 
                                                     func_lib::bind(&ContactPanel::onInvitation, this, _1, _2, _3, _4),
                                                     func_lib::bind(&ContactPanel::onInvitationRegisterFailed, this, _1));
}

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

void
ContactPanel::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_policy->checkVerificationPolicy(data, stepCount, onVerified, onVerifyFailed);

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

}

void
ContactPanel::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
ContactPanel::onCertData(const shared_ptr<const ndn::Interest>& interest, 
                         const shared_ptr<Data>& cert,
                         shared_ptr<ValidationRequest> previousStep)
{
  shared_ptr<ValidationRequest> nextStep = m_policy->checkVerificationPolicy(cert, 
                                                                                    previousStep->stepCount_, 
                                                                                    previousStep->onVerified_, 
                                                                                    previousStep->onVerifyFailed_);

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

void
ContactPanel::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, 
                            func_lib::bind(&ContactPanel::onCertData,
                                 this,
                                 _1,
                                 _2,
                                 nextStep),
                            func_lib::bind(&ContactPanel::onCertTimeout,
                                 this,
                                 _1,
                                 onVerifyFailed,
                                 data,
                                 nextStep));
 else
   onVerifyFailed(data);
}

void
ContactPanel::onInvitationRegisterFailed(const shared_ptr<const Name>& prefix)
{
  showError(QString::fromStdString("Cannot register invitation listening prefix"));
}

void
ContactPanel::onInvitation(const shared_ptr<const Name>& prefix, 
                           const shared_ptr<const Interest>& interest, 
                           Transport& transport, 
                           uint64_t registeredPrefixId)
{
  _LOG_DEBUG("Receive invitation!" << interest->getName().toUri());

  
  shared_ptr<ChronosInvitation> invitation;
  try{
    invitation = make_shared<ChronosInvitation>(interest->getName());
  }catch(std::exception& e){
    _LOG_ERROR("Exception: " << e.what());
    return;
  }
  
  Name chatroomName("/ndn/broadcast/chronos");
  chatroomName.append(invitation->getChatroom());
  map<Name, ChatDialog*>::iterator it = m_chatDialogs.find(chatroomName);
  if(it != m_chatDialogs.end())
    {
      _LOG_ERROR("Exisiting chatroom!");
      return;
    }

  shared_ptr<PublicKey> keyPtr = m_policy->getTrustedKey(invitation->getInviterCertificateName());

  SignatureSha256WithRsa invitationSig;
  Block sigBlock(invitation->getSignatureBits().buf(), invitation->getSignatureBits().size());
  invitationSig.setValue(sigBlock);
  if(static_cast<bool>(keyPtr) && Verifier::verifySignature(invitation->getSignedBlob(), invitationSig, *keyPtr))
    {
      shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>();
      // hack: incomplete certificate, we don't send it to the wire nor store it anywhere, we only use it to carry information
      certificate->setName(invitation->getInviterCertificateName());
      bool findCert = false;
      vector<shared_ptr<ContactItem> >::const_iterator it = m_contactList.begin();
      for(; it != m_contactList.end(); it++)
        {
          if((*it)->getNameSpace() == invitation->getInviterNameSpace())
            {
              certificate->setNotBefore((*it)->getSelfEndorseCertificate().getNotBefore());
              certificate->setNotAfter((*it)->getSelfEndorseCertificate().getNotAfter());
              findCert = true;
              break;
            }
        }
      if(findCert == false)
        {
          _LOG_ERROR("No SelfEndorseCertificate found!");
          return;
        }
      certificate->setPublicKeyInfo(*keyPtr);
      popChatInvitation(invitation, invitation->getInviterNameSpace(), certificate);
      return;
    }

  _LOG_DEBUG("Cannot find the inviter's key in trust anchors");

  Interest newInterest(invitation->getInviterCertificateName());
  OnVerified onVerified = func_lib::bind(&ContactPanel::onInvitationCertVerified, this, _1, invitation);
  OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactPanel::onInvitationCertVerifyFailed, this, _1);
  TimeoutNotify timeoutNotify = func_lib::bind(&ContactPanel::onInvitationCertTimeoutNotify, this);

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

void
ContactPanel::onInvitationCertVerified(const shared_ptr<Data>& data, 
                                       shared_ptr<ChronosInvitation> invitation)
{
  shared_ptr<IdentityCertificate> certificate = make_shared<IdentityCertificate>(*data);

  SignatureSha256WithRsa invitationSig;
  Block sigBlock(invitation->getSignatureBits().buf(), invitation->getSignatureBits().size());
  invitationSig.setValue(sigBlock);
  
  if(Verifier::verifySignature(invitation->getSignedBlob(), invitationSig, certificate->getPublicKeyInfo()))
    {
      Name keyName = certificate->getPublicKeyName();
      Name inviterNameSpace = keyName.getPrefix(-1);
      popChatInvitation(invitation, inviterNameSpace, certificate);
    }
}

void
ContactPanel::onInvitationCertVerifyFailed(const shared_ptr<Data>& data)
{ _LOG_DEBUG("Cannot verify invitation certificate!"); }

void
ContactPanel::onInvitationCertTimeoutNotify()
{ _LOG_DEBUG("interest for invitation certificate times out eventually!"); }

void
ContactPanel::popChatInvitation(shared_ptr<ChronosInvitation> invitation,
                                const Name& inviterNameSpace,
                                shared_ptr<IdentityCertificate> certificate)
{
  string alias;
  vector<shared_ptr<ContactItem> >::iterator it = m_contactList.begin();
  for(; it != m_contactList.end(); it++)
    if((*it)->getNameSpace() == inviterNameSpace)
      alias = (*it)->getAlias();

  if(it != m_contactList.end())
    return;

  m_invitationDialog->setInvitation(alias, invitation, certificate);
  emit newInvitationReady();
}

void
ContactPanel::collectEndorsement()
{
  m_collectStatus = make_shared<vector<bool> >();
  m_collectStatus->assign(m_contactList.size(), false);

  vector<shared_ptr<ContactItem> >::iterator it = m_contactList.begin();
  int count = 0;
  for(; it != m_contactList.end(); it++, count++)
    {
      Name interestName = (*it)->getNameSpace();
      interestName.append("DNS").append(m_defaultIdentity).append("ENDORSEE");
      Interest interest(interestName);
      interest.setInterestLifetime(1000);

      OnVerified onVerified = func_lib::bind(&ContactPanel::onDnsEndorseeVerified, this, _1, count);
      OnVerifyFailed onVerifyFailed = func_lib::bind(&ContactPanel::onDnsEndorseeVerifyFailed, this, _1, count);
      TimeoutNotify timeoutNotify = func_lib::bind(&ContactPanel::onDnsEndorseeTimeoutNotify, this, count);
  
      sendInterest(interest, onVerified, onVerifyFailed, timeoutNotify, 0);
    }
}

void
ContactPanel::onDnsEndorseeVerified(const shared_ptr<Data>& data, int count)
{
  Data endorseData;
  endorseData.wireDecode(Block(data->getContent().value(), data->getContent().value_size()));
  EndorseCertificate endorseCertificate(endorseData);

  m_contactManager->getContactStorage()->updateCollectEndorse(endorseCertificate);

  updateCollectStatus(count);
}

void
ContactPanel::onDnsEndorseeTimeoutNotify(int count)
{ updateCollectStatus(count); }

void
ContactPanel::onDnsEndorseeVerifyFailed(const shared_ptr<Data>& data, int count)
{ updateCollectStatus(count); }

void 
ContactPanel::updateCollectStatus(int count)
{
  m_collectStatus->at(count) = true;
  vector<bool>::const_iterator it = m_collectStatus->begin();
  for(; it != m_collectStatus->end(); it++)
    if(*it == false)
      return;

  m_contactManager->publishEndorsedDataInDns(m_defaultIdentity);
}

static std::string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789");

string
ContactPanel::getRandomString()
{
  string randStr;
  boost::random::random_device rng;
  boost::random::uniform_int_distribution<> index_dist(0, chars.size() - 1);
  for (int i = 0; i < 10; i ++)
  {
    randStr += chars[index_dist(rng)];
  }
  return randStr;
}

void
ContactPanel::showError(const QString& msg){
  QMessageBox::critical(this, tr("Chronos"), msg, QMessageBox::Ok);
  exit(1);
}

void
ContactPanel::showWarning(const QString& msg){
  QMessageBox::information(this, tr("Chronos"), msg);
}

void
ContactPanel::updateSelection(const QItemSelection &selected,
			      const QItemSelection &deselected)
{
  QModelIndexList items = selected.indexes();
  QString text = m_contactListModel->data(items.first(), Qt::DisplayRole).toString();
  string alias = text.toStdString();

  int i = 0;
  for(; i < m_contactList.size(); i++)
    {
      if(alias == m_contactList[i]->getAlias())
        break;
    }
  
  m_currentSelectedContact = m_contactList[i];
  ui->NameData->setText(QString::fromStdString(m_currentSelectedContact->getName()));
  ui->NameSpaceData->setText(QString::fromStdString(m_currentSelectedContact->getNameSpace().toUri()));
  ui->InstitutionData->setText(QString::fromStdString(m_currentSelectedContact->getInstitution()));

  if(m_currentSelectedContact->isIntroducer())
    {
      ui->isIntroducer->setChecked(true);
      ui->addScope->setEnabled(true);
      ui->deleteScope->setEnabled(true);     
      ui->trustScopeList->setEnabled(true);

      string filter("contact_namespace = '");
      filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");

      m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
      m_trustScopeModel->setTable("TrustScope");
      m_trustScopeModel->setFilter(filter.c_str());
      m_trustScopeModel->select();
      m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
      m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
      m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));

      ui->trustScopeList->setModel(m_trustScopeModel);
      ui->trustScopeList->setColumnHidden(0, true);
      ui->trustScopeList->setColumnHidden(1, true);
      ui->trustScopeList->show();
    }
  else
    {
      ui->isIntroducer->setChecked(false);
      ui->addScope->setEnabled(false);
      ui->deleteScope->setEnabled(false);

      string filter("contact_namespace = '");
      filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");

      m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
      m_trustScopeModel->setTable("TrustScope");
      m_trustScopeModel->setFilter(filter.c_str());
      m_trustScopeModel->select();
      m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
      m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
      m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));

      ui->trustScopeList->setModel(m_trustScopeModel);
      ui->trustScopeList->setColumnHidden(0, true);
      ui->trustScopeList->setColumnHidden(1, true);
      ui->trustScopeList->show();

      ui->trustScopeList->setEnabled(false);
    }

  string filter("profile_identity = '");
  filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");

  m_endorseDataModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
  m_endorseDataModel->setTable("ContactProfile");
  m_endorseDataModel->setFilter(filter.c_str());
  m_endorseDataModel->select();
  
  m_endorseDataModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Identity"));
  m_endorseDataModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Type"));
  m_endorseDataModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Value"));
  m_endorseDataModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Endorse"));

  ui->endorseList->setModel(m_endorseDataModel);
  ui->endorseList->setColumnHidden(0, true);
  ui->endorseList->resizeColumnToContents(1);
  ui->endorseList->resizeColumnToContents(2);
  ui->endorseList->setItemDelegateForColumn(3, m_endorseComboBoxDelegate);
  ui->endorseList->show();
}

void
ContactPanel::updateDefaultIdentity(const QString& identity, const QString& nickName)
{ 
  // _LOG_DEBUG(identity.toStdString());
  Name defaultIdentity = Name(identity.toStdString());
  Name defaultCertName = m_keyChain->getDefaultCertificateNameForIdentity(defaultIdentity);
  if(defaultCertName.size() == 0)
    {
      showWarning(QString::fromStdString("Corresponding certificate is missing!\nHave you installed the certificate?"));
      return;
    }
  m_defaultIdentity = defaultIdentity;
  m_profileEditor->setCurrentIdentity(m_defaultIdentity);
  m_nickName = nickName.toStdString();
  m_face->unsetInterestFilter(m_invitationListenerId);
  m_contactManager->setDefaultIdentity(m_defaultIdentity);
  setInvitationListener();
  collectEndorsement();
}

void
ContactPanel::openProfileEditor()
{ m_profileEditor->show(); }

void
ContactPanel::openAddContactPanel()
{ m_addContactPanel->show(); }

void
ContactPanel::openBrowseContactDialog()
{ 
  m_browseContactDialog->show(); 
  emit refreshCertDirectory();
}

void
ContactPanel::removeContactButton()
{
  QItemSelectionModel* selectionModel = ui->ContactList->selectionModel();
  QModelIndexList selectedList = selectionModel->selectedIndexes();
  QModelIndexList::iterator it = selectedList.begin();
  for(; it != selectedList.end(); it++)
    {
      string alias =  m_contactListModel->data(*it, Qt::DisplayRole).toString().toStdString();
      vector<shared_ptr<ContactItem> >::iterator contactIt = m_contactList.begin();
      for(; contactIt != m_contactList.end(); contactIt++)
        {
          if((*contactIt)->getAlias() == alias)
            {
              m_contactManager->getContactStorage()->removeContact((*contactIt)->getNameSpace());
              m_contactList.erase(contactIt);
              break;
            }
        }
    }
  refreshContactList();
}

void
ContactPanel::openInvitationDialog()
{ m_invitationDialog->show(); }

void
ContactPanel::addContactIntoPanelPolicy(const Name& contactNameSpace)
{
  shared_ptr<ContactItem> contact = m_contactManager->getContact(contactNameSpace);
  if(static_cast<bool>(contact))
    m_policy->addTrustAnchor(contact->getSelfEndorseCertificate());
}

void
ContactPanel::removeContactFromPanelPolicy(const Name& keyName)
{ m_policy->removeTrustAnchor(keyName); }

void
ContactPanel::refreshContactList()
{
  m_contactList.clear();
  m_contactManager->getContactItemList(m_contactList);
  QStringList contactNameList;
  for(int i = 0; i < m_contactList.size(); i++)
    contactNameList << QString::fromStdString(m_contactList[i]->getAlias());

  m_contactListModel->setStringList(contactNameList);
}

void
ContactPanel::showContextMenu(const QPoint& pos)
{
  QMenu menu(ui->ContactList);
  menu.addAction(m_menuInvite);
  connect(m_menuInvite, SIGNAL(triggered()),
          this, SLOT(openStartChatDialog()));
  menu.addSeparator();
  menu.addAction(m_menuAlias);
  connect(m_menuAlias, SIGNAL(triggered()),
          this, SLOT(openSetAliasDialog()));
  menu.exec(ui->ContactList->mapToGlobal(pos));

}

void
ContactPanel::openSetAliasDialog()
{
  m_setAliasDialog->setTargetIdentity(m_currentSelectedContact->getNameSpace().toUri());
  m_setAliasDialog->show();
}

void
ContactPanel::openSettingDialog()
{
  m_settingDialog->setIdentity(m_defaultIdentity.toUri(), m_nickName);
  m_settingDialog->show();
}

void
ContactPanel::openStartChatDialog()
{
  Name chatroom("/ndn/broadcast/chronos");
  chatroom.append(string("chatroom-") + getRandomString());

  m_startChatDialog->setInvitee(m_currentSelectedContact->getNameSpace().toUri(), chatroom.toUri());
  m_startChatDialog->show();
}

// For inviter
void
ContactPanel::startChatroom(const QString& chatroom, const QString& invitee, bool isIntroducer)
{
  Name chatroomName(chatroom.toStdString());

  Name inviteeNamespace(invitee.toStdString());
  shared_ptr<ContactItem> inviteeItem = m_contactManager->getContact(inviteeNamespace);

  ChatDialog* chatDialog = new ChatDialog(m_contactManager, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName);
  m_chatDialogs.insert(pair <Name, ChatDialog*> (chatroomName, chatDialog));

  connect(chatDialog, SIGNAL(closeChatDialog(const ndn::Name&)),
          this, SLOT(removeChatDialog(const ndn::Name&)));
  connect(chatDialog, SIGNAL(noNdnConnection(const QString&)),
          this, SLOT(showError(const QString&)));
  connect(chatDialog, SIGNAL(inivationRejection(const QString&)),
          this, SLOT(showWarning(const QString&)));

  // send invitation
  chatDialog->sendInvitation(inviteeItem, isIntroducer); 
  
  chatDialog->show();
}

// For Invitee
void
ContactPanel::startChatroom2(const ChronosInvitation& invitation, 
                             const IdentityCertificate& identityCertificate)
{
  shared_ptr<ContactItem> inviterItem = m_contactManager->getContact(invitation.getInviterNameSpace());

  Name chatroomName("/ndn/broadcast/chronos");
  chatroomName.append(invitation.getChatroom());

  ChatDialog* chatDialog = new ChatDialog(m_contactManager, chatroomName, m_localPrefix, m_defaultIdentity, m_nickName, true);

  connect(chatDialog, SIGNAL(closeChatDialog(const ndn::Name&)),
          this, SLOT(removeChatDialog(const ndn::Name&)));
  connect(chatDialog, SIGNAL(noNdnConnection(const QString&)),
          this, SLOT(showError(const QString&)));
  connect(chatDialog, SIGNAL(inivationRejection(const QString&)),
          this, SLOT(showWarning(const QString&)));

  chatDialog->addChatDataRule(invitation.getInviterPrefix(), identityCertificate, true);
  chatDialog->publishIntroCert(identityCertificate, true);

  chatDialog->addTrustAnchor(inviterItem->getSelfEndorseCertificate());
  
  m_chatDialogs.insert(pair <Name, ChatDialog*> (chatroomName, chatDialog));

  chatDialog->show();
}

void
ContactPanel::acceptInvitation(const ChronosInvitation& invitation, 
                               const IdentityCertificate& identityCertificate)
{
  Name dataName = invitation.getInterestName();
  time_t nowSeconds = time(NULL);
  struct tm current = *gmtime(&nowSeconds);
  MillisecondsSince1970 version = timegm(&current) * 1000.0;
  dataName.appendVersion(version);
  Data data(dataName);
  string content = m_localPrefix.toUri();
  data.setContent((const uint8_t *)&content[0], content.size());

  Name certificateName;
  Name inferredIdentity = m_policy->inferSigningIdentity(data.getName());

  if(inferredIdentity.getComponentCount() == 0)
    certificateName = m_keyChain->getDefaultCertificateName();
  else
    certificateName = m_keyChain->getDefaultCertificateNameForIdentity(inferredIdentity);   
  m_keyChain->sign(data, certificateName);

  m_face->put(data);

  startChatroom2(invitation, identityCertificate);
}

void
ContactPanel::rejectInvitation(const ChronosInvitation& invitation)
{
  Data data(invitation.getInterestName());
  string content("nack");
  data.setContent((const uint8_t *)&content[0], content.size());

  Name certificateName;
  Name inferredIdentity = m_policy->inferSigningIdentity(data.getName());
  if(inferredIdentity.getComponentCount() == 0)
    certificateName = m_keyChain->getDefaultCertificateName();
  else
    certificateName = m_keyChain->getDefaultCertificateNameForIdentity(inferredIdentity);   
  m_keyChain->sign(data, certificateName);

  m_face->put(data);
}

void
ContactPanel::isIntroducerChanged(int state)
{
  if(state == Qt::Checked)
    {
      ui->addScope->setEnabled(true);
      ui->deleteScope->setEnabled(true);
      ui->trustScopeList->setEnabled(true);
      
      string filter("contact_namespace = '");
      filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");

      m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
      m_trustScopeModel->setTable("TrustScope");
      m_trustScopeModel->setFilter(filter.c_str());
      m_trustScopeModel->select();
      m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
      m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
      m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));

      ui->trustScopeList->setModel(m_trustScopeModel);
      ui->trustScopeList->setColumnHidden(0, true);
      ui->trustScopeList->setColumnHidden(1, true);
      ui->trustScopeList->show();

      m_currentSelectedContact->setIsIntroducer(true);
    }
  else
    {
      ui->addScope->setEnabled(false);
      ui->deleteScope->setEnabled(false);

      string filter("contact_namespace = '");
      filter.append(m_currentSelectedContact->getNameSpace().toUri()).append("'");

      m_trustScopeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
      m_trustScopeModel->setTable("TrustScope");
      m_trustScopeModel->setFilter(filter.c_str());
      m_trustScopeModel->select();
      m_trustScopeModel->setHeaderData(0, Qt::Horizontal, QObject::tr("ID"));
      m_trustScopeModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Contact"));
      m_trustScopeModel->setHeaderData(2, Qt::Horizontal, QObject::tr("TrustScope"));

      ui->trustScopeList->setModel(m_trustScopeModel);
      ui->trustScopeList->setColumnHidden(0, true);
      ui->trustScopeList->setColumnHidden(1, true);
      ui->trustScopeList->show();

      ui->trustScopeList->setEnabled(false);

      m_currentSelectedContact->setIsIntroducer(false);
    }
  m_contactManager->getContactStorage()->updateIsIntroducer(m_currentSelectedContact->getNameSpace(), m_currentSelectedContact->isIntroducer());
}

void
ContactPanel::addScopeClicked()
{
  int rowCount = m_trustScopeModel->rowCount();
  QSqlRecord record;
  QSqlField identityField("contact_namespace", QVariant::String);
  record.append(identityField);
  record.setValue("contact_namespace", QString::fromStdString(m_currentSelectedContact->getNameSpace().toUri()));
  m_trustScopeModel->insertRow(rowCount);
  m_trustScopeModel->setRecord(rowCount, record);
}

void
ContactPanel::deleteScopeClicked()
{
  QItemSelectionModel* selectionModel = ui->trustScopeList->selectionModel();
  QModelIndexList indexList = selectionModel->selectedIndexes();

  int i = indexList.size() - 1;  
  for(; i >= 0; i--)
    m_trustScopeModel->removeRow(indexList[i].row());
    
  m_trustScopeModel->submitAll();
}

void
ContactPanel::saveScopeClicked()
{ m_trustScopeModel->submitAll(); }

void
ContactPanel::endorseButtonClicked()
{
  m_endorseDataModel->submitAll();
  m_contactManager->updateEndorseCertificate(m_currentSelectedContact->getNameSpace(), m_defaultIdentity);
}

void
ContactPanel::removeChatDialog(const ndn::Name& chatroomName)
{
  map<Name, ChatDialog*>::iterator it = m_chatDialogs.find(chatroomName);

  ChatDialog* deletedChat = NULL;
  if(it != m_chatDialogs.end())
    {
      deletedChat = it->second;
      m_chatDialogs.erase(it);      
    }
  if (deletedChat != NULL)
    delete deletedChat;
}

#if WAF
#include "contactpanel.moc"
#include "contactpanel.cpp.moc"
#endif
