/* -*- 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.h"
#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-cpp-dev/util/random.hpp>
#include <cryptopp/hex.h>
#include <cryptopp/files.h>
#include <queue>
#include "logging.h"
#endif

using namespace ndn;
using ndn::shared_ptr;
using namespace chronos;

INIT_LOGGER("ChatDialog");

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

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)

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).toEscapedString())
  , 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 std::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(std::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 std::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 std::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 ndn::Interest& interest)
{
  std::vector<Name> certNameList;
  m_sock->getIntroCertNames(certNameList);

  Chronos::IntroCertListMsg msg;

  std::vector<Name>::const_iterator it  = certNameList.begin();
  std::vector<Name>::const_iterator end = certNameList.end();
  for(; it != 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 std::string& msg)
{
  _LOG_DEBUG("ChatDialog::onCertListRegisterFailed failed: " + msg);
}

void
ChatDialog::onCertSingleInterest(const Name& prefix, const ndn::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 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)};
  std::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 ndn::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));
}

std::string
ChatDialog::getRandomString()
{
  uint32_t r = 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 ();
  std::map<std::string, bool> branches = logic.getBranchPrefixes();
  QMap<QString, DisplayUserPtr> roster = m_scene->getRosterFull();

  m_zombieList.clear();

  QMapIterator<QString, DisplayUserPtr> it(roster);
  std::map<std::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 std::map<Name, shared_ptr<TrustTreeNode> > NodeMap;

  std::vector<Name> certNameList;
  NodeMap nodeMap;

  m_sock->getIntroCertNames(certNameList);

  std::vector<Name>::const_iterator it  = certNameList.begin();
  std::vector<Name>::const_iterator end = certNameList.end();
  for(; it != 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();
  std::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();
      TrustTreeNodeList::iterator eeIt  = introducees.begin();
      TrustTreeNodeList::iterator eeEnd = introducees.end();

      for(; eeIt != eeEnd; eeIt++)
        {
          _LOG_DEBUG("introducee: " << (*eeIt)->name() << " visited: " << 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
    std::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 std::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())
  {
    std::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())
  {
    std::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, 
                                     interest.getName().size()-routablePrefixOffset, //RoutablePrefix will be removed before data is passed to the validator
                                     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());
}


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