/* -*- 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"
#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)
{
  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&)));
  }

  initializeSync();
}


ChatDialog::~ChatDialog()
{
  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 invation");
  // 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 (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 (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 Name& prefix, const 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);

  Data data(interest.getName());
  data.setContent(os.buf());
  m_keyChain.sign(data, m_myCertificate.getName());

  m_face->put(data);
}

void
ChatDialog::onCertListRegisterFailed(const Name& prefix, const 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);
    Data 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 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()/1000000000);
  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()/1000000000);
  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();
  }
}

// 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::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 shared_ptr<const 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;
  }

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

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) / 1000000000;
  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 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 Interest& interest, const shared_ptr<const Data>& data)
{
  Data innerData;
  innerData.wireDecode(data->getContent().blockFromValue());
  Sync::IntroCertificate introCert(innerData);
  m_sock->addParticipant(introCert);
  plotTrustTree();
}

void
ChatDialog::onIntroCertTimeout(const 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
