/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
 *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 *         Yingdi Yu <yingdi@cs.ucla.edu>
 */

#include "chat-dialog.hpp"
#include "ui_chat-dialog.h"

#include <QScrollBar>
#include <QMessageBox>
#include <QCloseEvent>

#ifndef Q_MOC_RUN
#include <sync-intro-certificate.h>
#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <ndn-cxx/util/random.hpp>
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include "cryptopp.hpp"
#include <queue>
#include "logging.h"

#define SECURITY_ENABLED false
#endif


// INIT_LOGGER("ChatDialog");

Q_DECLARE_METATYPE(std::vector<Sync::MissingDataInfo> )
Q_DECLARE_METATYPE(ndn::shared_ptr<const ndn::Data>)
Q_DECLARE_METATYPE(ndn::Interest)
Q_DECLARE_METATYPE(size_t)


namespace chronos {

using std::vector;
using std::string;
using std::map;
using std::queue;

using ndn::IdentityCertificate;
using ndn::SecRuleRelative;
using ndn::Face;
using ndn::OBufferStream;
using ndn::OnDataValidated;
using ndn::OnDataValidationFailed;


static const int HELLO_INTERVAL = FRESHNESS * 3 / 4;
static const uint8_t CHRONOS_RP_SEPARATOR[2] = {0xF0, 0x2E}; // %F0.

ChatDialog::ChatDialog(ContactManager* contactManager,
                       shared_ptr<Face> face,
                       const IdentityCertificate& myCertificate,
                       const Name& chatroomPrefix,
                       const Name& localPrefix,
                       const std::string& nick,
                       bool withSecurity,
                       QWidget* parent)
  : QDialog(parent)
  , ui(new Ui::ChatDialog)
  , m_contactManager(contactManager)
  , m_face(face)
  , m_myCertificate(myCertificate)
  , m_chatroomName(chatroomPrefix.get(-1).toUri())
  , m_chatroomPrefix(chatroomPrefix)
  , m_localPrefix(localPrefix)
  , m_useRoutablePrefix(false)
  , m_nick(nick)
  , m_lastMsgTime(time::toUnixTimestamp(time::system_clock::now()).count())
  , m_joined(false)
  , m_sock(NULL)
  , m_session(static_cast<uint64_t>(time::toUnixTimestamp(time::system_clock::now()).count()))
  , m_inviteListDialog(new InviteListDialog)
  //ymj
  //, m_trustModel(withSecurity)
{
  qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
  qRegisterMetaType<ndn::shared_ptr<const ndn::Data> >("ndn.DataPtr");
  qRegisterMetaType<ndn::Interest>("ndn.Interest");
  qRegisterMetaType<size_t>("size_t");

  m_scene = new DigestTreeScene(this);
  m_trustScene = new TrustTreeScene(this);
  m_rosterModel = new QStringListModel(this);
  m_timer = new QTimer(this);

  ui->setupUi(this);
  ui->syncTreeViewer->setScene(m_scene);
  m_scene->setSceneRect(m_scene->itemsBoundingRect());
  ui->syncTreeViewer->hide();
  ui->trustTreeViewer->setScene(m_trustScene);
  m_trustScene->setSceneRect(m_trustScene->itemsBoundingRect());
  ui->trustTreeViewer->hide();
  ui->listView->setModel(m_rosterModel);

  m_identity =
    IdentityCertificate::certificateNameToPublicKeyName(m_myCertificate.getName()).getPrefix(-1);

  updatePrefix();

  updateLabels();

  m_scene->setCurrentPrefix(QString(m_localChatPrefix.toUri().c_str()));
  m_scene->plot("Empty");

  connect(ui->lineEdit, SIGNAL(returnPressed()),
          this, SLOT(onReturnPressed()));
  connect(ui->syncTreeButton, SIGNAL(pressed()),
          this, SLOT(onSyncTreeButtonPressed()));
  connect(ui->trustTreeButton, SIGNAL(pressed()),
          this, SLOT(onTrustTreeButtonPressed()));
  connect(m_scene, SIGNAL(replot()),
          this, SLOT(onReplot()));
  connect(m_scene, SIGNAL(rosterChanged(QStringList)),
          this, SLOT(onRosterChanged(QStringList)));
  connect(m_timer, SIGNAL(timeout()),
          this, SLOT(onReplot()));

  connect(this, SIGNAL(processData(const ndn::shared_ptr<const ndn::Data>&, bool, bool)),
          this, SLOT(onProcessData(const ndn::shared_ptr<const ndn::Data>&, bool, bool)));
  connect(this, SIGNAL(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)),
          this, SLOT(onProcessTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
  connect(this, SIGNAL(reply(const ndn::Interest&,
                             const ndn::shared_ptr<const ndn::Data>&,
                             size_t, bool)),
          this, SLOT(onReply(const ndn::Interest&,
                             const ndn::shared_ptr<const ndn::Data>&,
                             size_t, bool)));
  connect(this, SIGNAL(replyTimeout(const ndn::Interest&, size_t)),
          this, SLOT(onReplyTimeout(const ndn::Interest&, size_t)));
  connect(this, SIGNAL(introCert(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&)),
          this, SLOT(onIntroCert(const ndn::Interest&, const ndn::shared_ptr<const ndn::Data>&)));
  connect(this, SIGNAL(introCertTimeout(const ndn::Interest&, int, const QString&)),
          this, SLOT(onIntroCertTimeout(const ndn::Interest&, int, const QString&)));

  if (withSecurity) {
    m_invitationValidator = make_shared<chronos::ValidatorInvitation>();
    m_dataRule = make_shared<SecRuleRelative>("([^<CHRONOCHAT-DATA>]*)<CHRONOCHAT-DATA><>",
                                              "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>$",
                                              "==", "\\1", "\\1", true);

    ui->inviteButton->setEnabled(true);
    ui->trustTreeButton->setEnabled(true);

    connect(ui->inviteButton, SIGNAL(clicked()),
            this, SLOT(onInviteListDialogRequested()));
    connect(m_inviteListDialog, SIGNAL(sendInvitation(const QString&)),
            this, SLOT(onSendInvitation(const QString&)));
    connect(this, SIGNAL(waitForContactList()),
            m_contactManager, SLOT(onWaitForContactList()));
    connect(m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
            m_inviteListDialog, SLOT(onContactAliasListReady(const QStringList&)));
    connect(m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
            m_inviteListDialog, SLOT(onContactIdListReady(const QStringList&)));

    m_trustModel = ChatroomInfo::TRUST_MODEL_WEBOFTRUST;
  }
  else
    m_trustModel = ChatroomInfo::TRUST_MODEL_NONE;

  initializeSync();
}


ChatDialog::~ChatDialog()
{
  if (SECURITY_ENABLED) {
    if (m_certListPrefixId)
      m_face->unsetInterestFilter(m_certListPrefixId);

    if (m_certSinglePrefixId)
      m_face->unsetInterestFilter(m_certSinglePrefixId);
  }

  if (m_sock != NULL) {
    sendLeave();
    delete m_sock;
    m_sock = NULL;
  }
}

// public methods:
void
ChatDialog::addSyncAnchor(const Invitation& invitation)
{
  // _LOG_DEBUG("Add sync anchor from invitation");
  // Add inviter certificate as trust anchor.
  m_sock->addParticipant(invitation.getInviterCertificate());
  plotTrustTree();

  // Ask inviter for IntroCertificate
  Name inviterNameSpace =
    IdentityCertificate::certificateNameToPublicKeyName(
      invitation.getInviterCertificate().getName()).getPrefix(-1);
  fetchIntroCert(inviterNameSpace, invitation.getInviterRoutingPrefix());
}

void
ChatDialog::processTreeUpdateWrapper(const vector<Sync::MissingDataInfo>& v,
                                     Sync::SyncSocket *sock)
{
  emit processTreeUpdate(v);
  // _LOG_DEBUG("<<< Tree update signal emitted");
}

void
ChatDialog::processDataWrapper(const shared_ptr<const Data>& data)
{
  emit processData(data, true, false);
  // _LOG_DEBUG("<<< " << data->getName() << " fetched");
}

void
ChatDialog::processDataNoShowWrapper(const shared_ptr<const Data>& data)
{
  emit processData(data, false, false);
}

void
ChatDialog::processRemoveWrapper(const string& prefix)
{
  // _LOG_DEBUG("Sync REMOVE signal received for prefix: " << prefix);
}

// protected methods:
void
ChatDialog::closeEvent(QCloseEvent *e)
{
  QMessageBox::information(this, tr("ChronoChat"),
                           tr("The chatroom will keep running in the "
                              "system tray. To close the chatroom, "
                              "choose <b>Close chatroom</b> in the "
                              "context memu of the system tray entry."));
  hide();
  e->ignore();
}

void
ChatDialog::changeEvent(QEvent *e)
{
  switch(e->type()) {
  case QEvent::ActivationChange:
    if (isActiveWindow()) {
      emit resetIcon();
    }
    break;
  default:
    break;
  }
}

void
ChatDialog::resizeEvent(QResizeEvent *e)
{
  fitView();
}

void
ChatDialog::showEvent(QShowEvent *e)
{
  fitView();
}

// private methods:
void
ChatDialog::updatePrefix()
{
  m_certListPrefix.clear();
  m_certSinglePrefix.clear();
  m_localChatPrefix.clear();
  m_chatPrefix.clear();
  m_chatPrefix.append(m_identity)
    .append("CHRONOCHAT-DATA")
    .append(m_chatroomName)
    .append(getRandomString());
  if (!m_localPrefix.isPrefixOf(m_identity)) {
    m_useRoutablePrefix = true;
    m_certListPrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
    m_certSinglePrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
    m_localChatPrefix.append(m_localPrefix).append(CHRONOS_RP_SEPARATOR, 2);
  }
  m_certListPrefix.append(m_identity).append("CHRONOCHAT-CERT-LIST").append(m_chatroomName);
  m_certSinglePrefix.append(m_identity).append("CHRONOCHAT-CERT-SINGLE").append(m_chatroomName);
  m_localChatPrefix.append(m_chatPrefix);

  if (SECURITY_ENABLED) {
    if (static_cast<bool>(m_certListPrefixId))
      m_face->unsetInterestFilter(m_certListPrefixId);

    m_certListPrefixId = m_face->setInterestFilter(m_certListPrefix,
                                                   bind(&ChatDialog::onCertListInterest,
                                                        this, _1, _2),
                                                   bind(&ChatDialog::onCertListRegisterFailed,
                                                        this, _1, _2));

    if (static_cast<bool>(m_certSinglePrefixId))
      m_face->unsetInterestFilter(m_certSinglePrefixId);

    m_certSinglePrefixId = m_face->setInterestFilter(m_certSinglePrefix,
                                                     bind(&ChatDialog::onCertSingleInterest,
                                                          this, _1, _2),
                                                     bind(&ChatDialog::onCertSingleRegisterFailed,
                                                          this, _1, _2));
  }
}

void
ChatDialog::updateLabels()
{
  QString settingDisp = QString("Chatroom: %1").arg(QString::fromStdString(m_chatroomName));
  ui->infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
  ui->infoLabel->setText(settingDisp);
  QString prefixDisp;
  Name privatePrefix("/private/local");
  if (privatePrefix.isPrefixOf(m_localChatPrefix)) {
    prefixDisp =
      QString("<Warning: no connection to hub or hub does not support prefix autoconfig.>\n"
              "<Prefix = %1>")
      .arg(QString::fromStdString(m_localChatPrefix.toUri()));
    ui->prefixLabel->setStyleSheet(
      "QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
  }
  else {
    prefixDisp = QString("<Prefix = %1>")
      .arg(QString::fromStdString(m_localChatPrefix.toUri()));
    ui->prefixLabel->setStyleSheet(
      "QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
  }
  ui->prefixLabel->setText(prefixDisp);
}

void
ChatDialog::initializeSync()
{

  m_sock = new Sync::SyncSocket(m_chatroomPrefix,
                                m_chatPrefix,
                                m_session,
                                m_useRoutablePrefix,
                                m_localPrefix,
                                m_face,
                                m_myCertificate,
                                m_dataRule,
                                bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
                                bind(&ChatDialog::processRemoveWrapper, this, _1));

  usleep(100000);

  QTimer::singleShot(600, this, SLOT(sendJoin()));
  m_timer->start(FRESHNESS * 1000);
  disableSyncTreeDisplay();
  QTimer::singleShot(2200, this, SLOT(enableSyncTreeDisplay()));
}

void
ChatDialog::sendInvitation(shared_ptr<Contact> contact, bool isIntroducer)
{
  // Add invitee as a trust anchor.
  m_invitationValidator->addTrustAnchor(contact->getPublicKeyName(),
                                        contact->getPublicKey());

  // Prepared an invitation interest without routable prefix.
  Invitation invitation(contact->getNameSpace(),
                        m_chatroomName,
                        m_localPrefix,
                        m_myCertificate);
  Interest tmpInterest(invitation.getUnsignedInterestName());
  m_keyChain.sign(tmpInterest, m_myCertificate.getName());

  // Get invitee's routable prefix
  // (ideally it will do some DNS lookup, but we assume everyone use /ndn/broadcast
  Name routablePrefix = getInviteeRoutablePrefix(contact->getNameSpace());

  // Check if we need to prepend the routable prefix to the interest name.
  bool requireRoutablePrefix = false;
  Name interestName;
  size_t routablePrefixOffset = 0;
  if (!routablePrefix.isPrefixOf(tmpInterest.getName())) {
    interestName.append(routablePrefix).append(CHRONOS_RP_SEPARATOR, 2);
    requireRoutablePrefix = true;
    routablePrefixOffset = routablePrefix.size() + 1;
  }
  interestName.append(tmpInterest.getName());

  // Send the invitation out
  Interest interest(interestName);
  interest.setMustBeFresh(true);
  // _LOG_DEBUG("sendInvitation: " << interest.getName());
  m_face->expressInterest(interest,
                          bind(&ChatDialog::replyWrapper,
                               this, _1, _2, routablePrefixOffset, isIntroducer),
                          bind(&ChatDialog::replyTimeoutWrapper,
                               this, _1, routablePrefixOffset));
}

void
ChatDialog::replyWrapper(const Interest& interest,
                         Data& data,
                         size_t routablePrefixOffset,
                         bool isIntroducer)
{
  // _LOG_DEBUG("ChatDialog::replyWrapper");
  emit reply(interest, data.shared_from_this(), routablePrefixOffset, isIntroducer);
  // _LOG_DEBUG("OK?");
}

void
ChatDialog::replyTimeoutWrapper(const Interest& interest,
                                size_t routablePrefixOffset)
{
  // _LOG_DEBUG("ChatDialog::replyTimeoutWrapper");
  emit replyTimeout(interest, routablePrefixOffset);
}

void
ChatDialog::onReplyValidated(const shared_ptr<const Data>& data,
                             size_t inviteeRoutablePrefixOffset,
                             bool isIntroducer)
{
  if (data->getName().size() <= inviteeRoutablePrefixOffset) {
    Invitation invitation(data->getName());
    invitationRejected(invitation.getInviteeNameSpace());
  }
  else {
    Name inviteePrefix;
    inviteePrefix.wireDecode(data->getName().get(inviteeRoutablePrefixOffset).blockFromValue());
    IdentityCertificate inviteeCert;
    inviteeCert.wireDecode(data->getContent().blockFromValue());
    invitationAccepted(inviteeCert, inviteePrefix, isIntroducer);
  }
}

void
ChatDialog::onReplyValidationFailed(const shared_ptr<const Data>& data,
                                    const string& failureInfo)
{
  // _LOG_DEBUG("Invitation reply cannot be validated: " + failureInfo + " ==> " +
  //            data->getName().toUri());
}

void
ChatDialog::invitationRejected(const Name& identity)
{
  QString msg = QString::fromStdString(identity.toUri()) + " rejected your invitation!";
  emit inivationRejection(msg);
}

void
ChatDialog::invitationAccepted(const IdentityCertificate& inviteeCert,
                               const Name& inviteePrefix,
                               bool isIntroducer)
{
  // Add invitee certificate as trust anchor.
  m_sock->addParticipant(inviteeCert);
  plotTrustTree();

  // Ask invitee for IntroCertificate.
  Name inviteeNameSpace =
    IdentityCertificate::certificateNameToPublicKeyName(inviteeCert.getName()).getPrefix(-1);
  fetchIntroCert(inviteeNameSpace, inviteePrefix);
}

void
ChatDialog::fetchIntroCert(const Name& identity, const Name& prefix)
{
  Name interestName;

  if (!prefix.isPrefixOf(identity))
    interestName.append(prefix).append(CHRONOS_RP_SEPARATOR, 2);

  interestName.append(identity)
    .append("CHRONOCHAT-CERT-LIST")
    .append(m_chatroomName)
    .appendVersion();

  Interest interest(interestName);
  interest.setMustBeFresh(true);

  m_face->expressInterest(interest,
                          bind(&ChatDialog::onIntroCertList, this, _1, _2),
                          bind(&ChatDialog::onIntroCertListTimeout, this, _1, 1,
                               "IntroCertList: " + interestName.toUri()));
}

void
ChatDialog::onIntroCertList(const Interest& interest, const Data& data)
{
  Chronos::IntroCertListMsg introCertList;
  if (!introCertList.ParseFromArray(data.getContent().value(), data.getContent().value_size()))
    return;

  for (int i = 0; i < introCertList.certname_size(); i++) {
    Name certName(introCertList.certname(i));
    Interest interest(certName);
    interest.setMustBeFresh(true);

    // _LOG_DEBUG("onIntroCertList: to fetch " << certName);

    m_face->expressInterest(interest,
                            bind(&ChatDialog::introCertWrapper, this, _1, _2),
                            bind(&ChatDialog::introCertTimeoutWrapper, this, _1, 0,
                                 QString("IntroCert: %1").arg(introCertList.certname(i).c_str())));
  }
}

void
ChatDialog::onIntroCertListTimeout(const Interest& interest, int retry, const string& msg)
{
  if (retry > 0) {
    m_face->expressInterest(interest,
                            bind(&ChatDialog::onIntroCertList, this, _1, _2),
                            bind(&ChatDialog::onIntroCertListTimeout, this, _1, retry - 1, msg));
  }
  else {
    // _LOG_DEBUG(msg << " TIMEOUT!");
  }
}

void
ChatDialog::introCertWrapper(const Interest& interest, Data& data)
{
  emit introCert(interest, data.shared_from_this());
}

void
ChatDialog::introCertTimeoutWrapper(const Interest& interest, int retry, const QString& msg)
{
  emit introCertTimeout(interest, retry, msg);
}

void
ChatDialog::onCertListInterest(const ndn::Name& prefix, const ndn::Interest& interest)
{
  vector<Name> certNameList;
  m_sock->getIntroCertNames(certNameList);

  Chronos::IntroCertListMsg msg;

  for (vector<Name>::const_iterator it = certNameList.begin(); it != certNameList.end(); it++) {
    Name certName;
    certName.append(m_certSinglePrefix).append(*it);
    msg.add_certname(certName.toUri());
  }
  OBufferStream os;
  msg.SerializeToOstream(&os);

  shared_ptr<Data> data = make_shared<Data>(interest.getName());
  data->setContent(os.buf());
  m_keyChain.sign(*data, m_myCertificate.getName());

  m_face->put(*data);
}

void
ChatDialog::onCertListRegisterFailed(const ndn::Name& prefix, const std::string& msg)
{
  _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
}

void
ChatDialog::onCertSingleInterest(const Name& prefix, const Interest& interest)
{
  try {
    Name certName = interest.getName().getSubName(prefix.size());
    const Sync::IntroCertificate& introCert = m_sock->getIntroCertificate(certName);

    shared_ptr<Data> data = make_shared<Data>(interest.getName());
    data->setContent(introCert.wireEncode());
    m_keyChain.sign(*data,  m_myCertificate.getName());
    m_face->put(*data);
  }
  catch(Sync::SyncSocket::Error& e) {
    return;
  }
}

void
ChatDialog::onCertSingleRegisterFailed(const Name& prefix, const std::string& msg)
{
  _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
}

void
ChatDialog::sendMsg(SyncDemo::ChatMessage &msg)
{
  // send msg
  OBufferStream os;
  msg.SerializeToOstream(&os);

  if (!msg.IsInitialized()) {
    // _LOG_DEBUG("Errrrr.. msg was not probally initialized " << __FILE__ <<
    //            ":" << __LINE__ << ". what is happening?");
    abort();
  }
  uint64_t nextSequence = m_sock->getNextSeq();
  m_sock->publishData(os.buf()->buf(), os.buf()->size(), FRESHNESS);

  m_lastMsgTime = time::toUnixTimestamp(time::system_clock::now()).count();

  Sync::MissingDataInfo mdi = {m_localChatPrefix.toUri(),
                               Sync::SeqNo(0),
                               Sync::SeqNo(nextSequence)};
  vector<Sync::MissingDataInfo> v;
  v.push_back(mdi);
  {
    boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
    m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
    m_scene->msgReceived(QString::fromStdString(m_localChatPrefix.toUri()),
                         QString::fromStdString(m_nick));
  }
}

void ChatDialog::disableSyncTreeDisplay()
{
  ui->syncTreeButton->setEnabled(false);
  ui->syncTreeViewer->hide();
  fitView();
}

void
ChatDialog::appendMessage(const SyncDemo::ChatMessage msg, bool isHistory)
{
  boost::recursive_mutex::scoped_lock lock(m_msgMutex);

  if (msg.type() == SyncDemo::ChatMessage::CHAT) {
    if (!msg.has_data()) {
      return;
    }

    if (msg.from().empty() || msg.data().empty()) {
      return;
    }

    if (!msg.has_timestamp()) {
      return;
    }

    // if (m_history.size() == MAX_HISTORY_ENTRY)
    // {
    //   m_history.dequeue();
    // }

    // m_history.enqueue(msg);

    QTextCharFormat nickFormat;
    nickFormat.setForeground(Qt::darkGreen);
    nickFormat.setFontWeight(QFont::Bold);
    nickFormat.setFontUnderline(true);
    nickFormat.setUnderlineColor(Qt::gray);

    QTextCursor cursor(ui->textEdit->textCursor());
    cursor.movePosition(QTextCursor::End);
    QTextTableFormat tableFormat;
    tableFormat.setBorder(0);
    QTextTable *table = cursor.insertTable(1, 2, tableFormat);
    QString from = QString("%1 ").arg(msg.from().c_str());
    QTextTableCell fromCell = table->cellAt(0, 0);
    fromCell.setFormat(nickFormat);
    fromCell.firstCursorPosition().insertText(from);

    time_t timestamp = msg.timestamp();
    printTimeInCell(table, timestamp);

    QTextCursor nextCursor(ui->textEdit->textCursor());
    nextCursor.movePosition(QTextCursor::End);
    table = nextCursor.insertTable(1, 1, tableFormat);
    table->cellAt(0, 0).firstCursorPosition().insertText(QString::fromUtf8(msg.data().c_str()));
    if (!isHistory) {
      showMessage(from, QString::fromUtf8(msg.data().c_str()));
    }
  }

  if (msg.type() == SyncDemo::ChatMessage::JOIN || msg.type() == SyncDemo::ChatMessage::LEAVE) {
    QTextCharFormat nickFormat;
    nickFormat.setForeground(Qt::gray);
    nickFormat.setFontWeight(QFont::Bold);
    nickFormat.setFontUnderline(true);
    nickFormat.setUnderlineColor(Qt::gray);

    QTextCursor cursor(ui->textEdit->textCursor());
    cursor.movePosition(QTextCursor::End);
    QTextTableFormat tableFormat;
    tableFormat.setBorder(0);
    QTextTable *table = cursor.insertTable(1, 2, tableFormat);
    QString action;
    if (msg.type() == SyncDemo::ChatMessage::JOIN) {
      action = "enters room";
    }
    else {
      action = "leaves room";
    }

    QString from = QString("%1 %2  ").arg(msg.from().c_str()).arg(action);
    QTextTableCell fromCell = table->cellAt(0, 0);
    fromCell.setFormat(nickFormat);
    fromCell.firstCursorPosition().insertText(from);

    time_t timestamp = msg.timestamp();
    printTimeInCell(table, timestamp);
  }

  QScrollBar *bar = ui->textEdit->verticalScrollBar();
  bar->setValue(bar->maximum());
}

void
ChatDialog::processRemove(QString prefix)
{
  // _LOG_DEBUG("<<< remove node for prefix" << prefix.toStdString());

  bool removed = m_scene->removeNode(prefix);
  if (removed) {
    boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
    m_scene->plot(m_sock->getRootDigest().c_str());
  }
}

Name
ChatDialog::getInviteeRoutablePrefix(const Name& invitee)
{
  return Name("/ndn/broadcast");
}

void
ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
  msg.set_from(m_nick);
  msg.set_to(m_chatroomName);
  msg.set_data(text.toStdString());
  int32_t seconds =
    static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000);
  msg.set_timestamp(seconds);
  msg.set_type(SyncDemo::ChatMessage::CHAT);
}

void
ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg,
                               SyncDemo::ChatMessage::ChatMessageType type)
{
  msg.set_from(m_nick);
  msg.set_to(m_chatroomName);
  int32_t seconds =
    static_cast<int32_t>(time::toUnixTimestamp(time::system_clock::now()).count()/1000);
  msg.set_timestamp(seconds);
  msg.set_type(type);
}

QString
ChatDialog::formatTime(time_t timestamp)
{
  struct tm *tm_time = localtime(&timestamp);
  int hour = tm_time->tm_hour;
  QString amOrPM;
  if (hour > 12) {
    hour -= 12;
    amOrPM = "PM";
  }
  else {
    amOrPM = "AM";
    if (hour == 0) {
      hour = 12;
    }
  }

  char textTime[12];
  sprintf(textTime, "%d:%02d:%02d %s",
          hour, tm_time->tm_min, tm_time->tm_sec, amOrPM.toStdString().c_str());
  return QString(textTime);
}

void
ChatDialog::printTimeInCell(QTextTable *table, time_t timestamp)
{
  QTextCharFormat timeFormat;
  timeFormat.setForeground(Qt::gray);
  timeFormat.setFontUnderline(true);
  timeFormat.setUnderlineColor(Qt::gray);
  QTextTableCell timeCell = table->cellAt(0, 1);
  timeCell.setFormat(timeFormat);
  timeCell.firstCursorPosition().insertText(formatTime(timestamp));
}

string
ChatDialog::getRandomString()
{
  uint32_t r = ndn::random::generateWord32();
  std::stringstream ss;
  {
    using namespace CryptoPP;
    StringSource(reinterpret_cast<uint8_t*>(&r), 4, true,
                 new HexEncoder(new FileSink(ss), false));

  }

  return ss.str();
}

void
ChatDialog::showMessage(const QString& from, const QString& data)
{
  if (!isActiveWindow())
    emit showChatMessage(QString::fromStdString(m_chatroomName),
                         from, data);
}

void
ChatDialog::fitView()
{
  boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
  QRectF rect = m_scene->itemsBoundingRect();
  m_scene->setSceneRect(rect);
  ui->syncTreeViewer->fitInView(m_scene->itemsBoundingRect(), Qt::KeepAspectRatio);

  QRectF trustRect = m_trustScene->itemsBoundingRect();
  m_trustScene->setSceneRect(trustRect);
  ui->trustTreeViewer->fitInView(m_trustScene->itemsBoundingRect(), Qt::KeepAspectRatio);
}

void
ChatDialog::summonReaper()
{
  Sync::SyncLogic &logic = m_sock->getLogic ();
  map<string, bool> branches = logic.getBranchPrefixes();
  QMap<QString, DisplayUserPtr> roster = m_scene->getRosterFull();

  m_zombieList.clear();

  QMapIterator<QString, DisplayUserPtr> it(roster);
  map<string, bool>::iterator mapIt;
  while (it.hasNext()) {
    it.next();
    DisplayUserPtr p = it.value();
    if (p != DisplayUserNullPtr) {
      mapIt = branches.find(p->getPrefix().toStdString());
      if (mapIt != branches.end()) {
        mapIt->second = true;
      }
    }
  }

  for (mapIt = branches.begin(); mapIt != branches.end(); ++mapIt) {
    // this is zombie. all active users should have been marked true
    if (! mapIt->second) {
      m_zombieList.append(mapIt->first.c_str());
    }
  }

  m_zombieIndex = 0;

  // start reaping
  reap();
}

void
ChatDialog::getTree(TrustTreeNodeList& nodeList)
{
  typedef map<Name, shared_ptr<TrustTreeNode> > NodeMap;

  vector<Name> certNameList;
  NodeMap nodeMap;

  m_sock->getIntroCertNames(certNameList);

  for (vector<Name>::const_iterator it = certNameList.begin(); it != certNameList.end(); it++) {
    Name introducerCertName;
    Name introduceeCertName;

    introducerCertName.wireDecode(it->get(-2).blockFromValue());
    introduceeCertName.wireDecode(it->get(-3).blockFromValue());

    Name introducerName =
      IdentityCertificate::certificateNameToPublicKeyName(introducerCertName).getPrefix(-1);
    Name introduceeName =
      IdentityCertificate::certificateNameToPublicKeyName(introduceeCertName).getPrefix(-1);

    NodeMap::iterator introducerIt = nodeMap.find(introducerName);
    if (introducerIt == nodeMap.end()) {
      shared_ptr<TrustTreeNode> introducerNode(new TrustTreeNode(introducerName));
      nodeMap[introducerName] = introducerNode;
    }
    shared_ptr<TrustTreeNode> erNode = nodeMap[introducerName];

    NodeMap::iterator introduceeIt = nodeMap.find(introduceeName);
    if (introduceeIt == nodeMap.end()) {
      shared_ptr<TrustTreeNode> introduceeNode(new TrustTreeNode(introduceeName));
      nodeMap[introduceeName] = introduceeNode;
    }
    shared_ptr<TrustTreeNode> eeNode = nodeMap[introduceeName];

    erNode->addIntroducee(eeNode);
    eeNode->addIntroducer(erNode);
  }

  nodeList.clear();
  queue<shared_ptr<TrustTreeNode> > nodeQueue;

  NodeMap::iterator nodeIt = nodeMap.find(m_identity);
  if (nodeIt == nodeMap.end())
    return;

  nodeQueue.push(nodeIt->second);
  nodeIt->second->setLevel(0);
  while (!nodeQueue.empty()) {
    shared_ptr<TrustTreeNode>& node = nodeQueue.front();
    node->setVisited();

    TrustTreeNodeList& introducees = node->getIntroducees();
    for (TrustTreeNodeList::iterator eeIt = introducees.begin();
         eeIt != introducees.end(); eeIt++) {
      // _LOG_DEBUG("introducee: " << (*eeIt)->name() <<
      //            " visited: " << std::boolalpha << (*eeIt)->visited());
      if (!(*eeIt)->visited()) {
        nodeQueue.push(*eeIt);
        (*eeIt)->setLevel(node->level()+1);
      }
    }

    nodeList.push_back(node);
    nodeQueue.pop();
  }
}

void
ChatDialog::plotTrustTree()
{
  TrustTreeNodeList nodeList;

  getTree(nodeList);
  {
    boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
    m_trustScene->plotTrustTree(nodeList);
    fitView();
  }
}

shared_ptr<ChatroomInfo>
ChatDialog::getChatroomInfo() const
{
  shared_ptr<ChatroomInfo> chatroom = make_shared<ChatroomInfo>();
  chatroom->setName(Name::Component(m_chatroomName));

  Roster roster = m_scene->getRosterFull();
  Roster_iterator it = roster.begin();

  for(it = roster.begin(); it != roster.end(); ++it )
  {
    Name participant = Name(it.key().toStdString()).getPrefix(-3);
    chatroom->addParticipant(participant);
  }

  chatroom->setTrustModel(m_trustModel);
  return chatroom;
}


// public slots:
void
ChatDialog::onLocalPrefixUpdated(const QString& localPrefix)
{
  Name newLocalPrefix(localPrefix.toStdString());
  if (!newLocalPrefix.empty() && newLocalPrefix != m_localPrefix) {
    // Update localPrefix
    m_localPrefix = newLocalPrefix;

    updatePrefix();
    updateLabels();
    m_scene->setCurrentPrefix(QString(m_localChatPrefix.toUri().c_str()));

    if (m_sock != NULL) {
      {
        boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
        m_scene->clearAll();
        m_scene->plot("Empty");
      }

      ui->textEdit->clear();

      if (m_joined) {
        sendLeave();
      }

      delete m_sock;
      m_sock = NULL;

      usleep(100000);
      m_sock = new Sync::SyncSocket(m_chatroomPrefix,
                                    m_chatPrefix,
                                    m_session,
                                    m_useRoutablePrefix,
                                    m_localPrefix,
                                    m_face,
                                    m_myCertificate,
                                    m_dataRule,
                                    bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
                                    bind(&ChatDialog::processRemoveWrapper, this, _1));
      usleep(100000);
      QTimer::singleShot(600, this, SLOT(sendJoin()));
      m_timer->start(FRESHNESS * 1000);
      disableSyncTreeDisplay();
      QTimer::singleShot(2200, this, SLOT(enableSyncTreeDisplay()));
    }
    else
      initializeSync();
  }
  else
    if (m_sock == NULL)
      initializeSync();

  fitView();
}

void
ChatDialog::onShow()
{
  this->show();
  this->raise();
  this->activateWindow();
}

void
ChatDialog::onClose()
{
  hide();
  emit closeChatDialog(QString::fromStdString(m_chatroomName));
}


// private slots:
void
ChatDialog::onReturnPressed()
{
  QString text = ui->lineEdit->text();
  if (text.isEmpty())
    return;

  ui->lineEdit->clear();

  if (text.startsWith("boruoboluomi")) {
    summonReaper ();
    // reapButton->show();
    fitView();
    return;
  }

  if (text.startsWith("minimanihong")) {
    // reapButton->hide();
    fitView();
    return;
  }

  SyncDemo::ChatMessage msg;
  formChatMessage(text, msg);

  appendMessage(msg);

  sendMsg(msg);

  fitView();
}

void
ChatDialog::onSyncTreeButtonPressed()
{
  if (ui->syncTreeViewer->isVisible()) {
    ui->syncTreeViewer->hide();
    ui->syncTreeButton->setText("Show ChronoSync Tree");
  }
  else {
    ui->syncTreeViewer->show();
    ui->syncTreeButton->setText("Hide ChronoSync Tree");
  }

  fitView();
}

void
ChatDialog::onTrustTreeButtonPressed()
{
  if (ui->trustTreeViewer->isVisible()) {
    ui->trustTreeViewer->hide();
    ui->trustTreeButton->setText("Show Trust Tree");
  }
  else {
    ui->trustTreeViewer->show();
    ui->trustTreeButton->setText("Hide Trust Tree");
  }

  fitView();
}

void
ChatDialog::onProcessData(const ndn::shared_ptr<const ndn::Data>& data, bool show, bool isHistory)
{
  SyncDemo::ChatMessage msg;
  bool corrupted = false;
  if (!msg.ParseFromArray(data->getContent().value(), data->getContent().value_size())) {
    // _LOG_DEBUG("Errrrr.. Can not parse msg with name: " <<
    //            data->getName() << ". what is happening?");
    // nasty stuff: as a remedy, we'll form some standard msg for inparsable msgs
    msg.set_from("inconnu");
    msg.set_type(SyncDemo::ChatMessage::OTHER);
    corrupted = true;
  }

  //std::cout << "onProcessData: " << show << std::endl;
  //std::cout << "onProcessData: " << corrupted << std::endl;

  // display msg received from network
  // we have to do so; this function is called by ccnd thread
  // so if we call appendMsg directly
  // Qt crash as "QObject: Cannot create children for a parent that is in a different thread"
  // the "cannonical" way to is use signal-slot
  if (show && !corrupted) {
    appendMessage(msg, isHistory);
  }

  if (!isHistory) {
    // update the tree view
    string prefix = data->getName().getPrefix(-2).toUri();
    // _LOG_DEBUG("<<< updating scene for" << prefix << ": " << msg.from());
    if (msg.type() == SyncDemo::ChatMessage::LEAVE) {
      processRemove(prefix.c_str());
    }
    else {
      boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
      m_scene->msgReceived(prefix.c_str(), msg.from().c_str());
    }
  }
  fitView();
}

void
ChatDialog::onProcessTreeUpdate(const vector<Sync::MissingDataInfo>& v)
{
  _LOG_DEBUG("<<< processing Tree Update");

  if (v.empty()) {
    return;
  }

  // reflect the changes on digest tree
  {
    boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
    m_scene->processUpdate(v, m_sock->getRootDigest().c_str());
  }

  int n = v.size();
  int totalMissingPackets = 0;
  for (int i = 0; i < n; i++) {
    totalMissingPackets += v[i].high.getSeq() - v[i].low.getSeq() + 1;
  }

  for (int i = 0; i < n; i++) {
    if (totalMissingPackets < 4) {
      for (Sync::SeqNo seq = v[i].low; seq <= v[i].high; ++seq) {
        m_sock->fetchData(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1), 2);
        _LOG_DEBUG("<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq());
      }
    }
    else {
      m_sock->fetchData(v[i].prefix, v[i].high,
                        bind(&ChatDialog::processDataNoShowWrapper, this, _1), 2);
    }
  }
  // adjust the view
  fitView();
}

void
ChatDialog::onReplot()
{
  boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
  m_scene->plot(m_sock->getRootDigest().c_str());
  fitView();
}

void
ChatDialog::onRosterChanged(QStringList staleUserList)
{
  boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
  QStringList rosterList = m_scene->getRosterList();
  m_rosterModel->setStringList(rosterList);
  QString user;
  QStringListIterator it(staleUserList);
  while (it.hasNext()) {
    string nick = it.next().toStdString();
    if (nick.empty())
      continue;

    SyncDemo::ChatMessage msg;
    formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
    msg.set_from(nick);
    appendMessage(msg);
  }
  plotTrustTree();

  emit rosterChanged(*getChatroomInfo());
}

void
ChatDialog::onInviteListDialogRequested()
{
  emit waitForContactList();
  m_inviteListDialog->setInviteLabel(m_chatroomPrefix.toUri());
  m_inviteListDialog->show();
}

void
ChatDialog::sendJoin()
{
  m_joined = true;
  SyncDemo::ChatMessage msg;
  formControlMessage(msg, SyncDemo::ChatMessage::JOIN);
  sendMsg(msg);
  boost::random::random_device rng;
  boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
  m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
  QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
}

void
ChatDialog::sendHello()
{
  int64_t now = time::toUnixTimestamp(time::system_clock::now()).count();
  int elapsed = (now - m_lastMsgTime) / 1000;
  if (elapsed >= m_randomizedInterval / 1000) {
    SyncDemo::ChatMessage msg;
    formControlMessage(msg, SyncDemo::ChatMessage::HELLO);
    sendMsg(msg);
    boost::random::random_device rng;
    boost::random::uniform_int_distribution<> uniform(1, FRESHNESS / 5 * 1000);
    m_randomizedInterval = HELLO_INTERVAL * 1000 + uniform(rng);
    QTimer::singleShot(m_randomizedInterval, this, SLOT(sendHello()));
  }
  else {
    QTimer::singleShot((m_randomizedInterval - elapsed * 1000), this, SLOT(sendHello()));
  }
}

void
ChatDialog::sendLeave()
{
  SyncDemo::ChatMessage msg;
  formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
  sendMsg(msg);
  usleep(500000);
  m_sock->leave();
  usleep(5000);
  m_joined = false;
  // _LOG_DEBUG("Sync REMOVE signal sent");
}

void ChatDialog::enableSyncTreeDisplay()
{
  ui->syncTreeButton->setEnabled(true);
  // treeViewer->show();
  // fitView();
}

void
ChatDialog::reap()
{
  if (m_zombieIndex < m_zombieList.size()) {
    string prefix = m_zombieList.at(m_zombieIndex).toStdString();
    m_sock->remove(prefix);
    // _LOG_DEBUG("Reaped: prefix = " << prefix);
    m_zombieIndex++;
    // reap again in 10 seconds
    QTimer::singleShot(10000, this, SLOT(reap()));
  }
}

void
ChatDialog::onSendInvitation(QString invitee)
{
  Name inviteeNamespace(invitee.toStdString());
  shared_ptr<Contact> inviteeItem = m_contactManager->getContact(inviteeNamespace);
  sendInvitation(inviteeItem, true);
}

void
ChatDialog::onReply(const Interest& interest,
                    const shared_ptr<const Data>& data,
                    size_t routablePrefixOffset,
                    bool isIntroducer)
{
  OnDataValidated onValidated = bind(&ChatDialog::onReplyValidated,
                                     this, _1,
                                     //RoutablePrefix will be removed before passing to validator
                                     interest.getName().size()-routablePrefixOffset,
                                     isIntroducer);

  OnDataValidationFailed onFailed = bind(&ChatDialog::onReplyValidationFailed,
                                         this, _1, _2);

  if (routablePrefixOffset > 0) {
    // It is an encapsulated packet, we only validate the inner packet.
    shared_ptr<Data> innerData = make_shared<Data>();
    innerData->wireDecode(data->getContent().blockFromValue());
    m_invitationValidator->validate(*innerData, onValidated, onFailed);
  }
  else
    m_invitationValidator->validate(*data, onValidated, onFailed);
}

void
ChatDialog::onReplyTimeout(const ndn::Interest& interest,
                           size_t routablePrefixOffset)
{
  Name interestName;
  if (routablePrefixOffset > 0)
    interestName = interest.getName().getSubName(routablePrefixOffset);
  else
    interestName = interest.getName();

  Invitation invitation(interestName);

  QString msg = QString::fromUtf8("Your invitation to ") +
    QString::fromStdString(invitation.getInviteeNameSpace().toUri()) + " times out!";
  emit inivationRejection(msg);
}

void
ChatDialog::onIntroCert(const ndn::Interest& interest, const ndn::shared_ptr<const ndn::Data>& data)
{
  Data innerData;
  innerData.wireDecode(data->getContent().blockFromValue());
  Sync::IntroCertificate introCert(innerData);
  m_sock->addParticipant(introCert);
  plotTrustTree();
}

void
ChatDialog::onIntroCertTimeout(const ndn::Interest& interest, int retry, const QString& msg)
{
  // _LOG_DEBUG("onIntroCertTimeout: " << msg.toStdString());
}

} // namespace chronos


#if WAF
#include "chat-dialog.moc"
// #include "chat-dialog.cpp.moc"
#endif
