#include "chatdialog.h"

#include "settingdialog.h"

#include <QtGui>
#include <QTimer>
#include <QMetaType>
#include <QMessageBox>

#ifndef Q_MOC_RUN
#include <ctime>
#include <iostream>

#include <boost/random/random_device.hpp>
#include <boost/random/uniform_int_distribution.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>

#include <stdio.h>
#endif

#define BROADCAST_PREFIX_FOR_SYNC_DEMO "/ndn/broadcast/chronos"
#define LOCAL_PREFIX_QUERY "/local/ndn/prefix"
#define DEFAULT_LOCAL_PREFIX "/private/local"
#define CCN_EXEC  "/usr/local/bin/ccnpeek"

static const int HELLO_INTERVAL = FRESHNESS * 3 / 4;  // seconds

ChatDialog::ChatDialog(QWidget *parent)
  : QDialog(parent), m_sock(NULL), m_lastMsgTime(0), m_historyInitialized(false), m_joined(false)
{
  // have to register this, otherwise
  // the signal-slot system won't recognize this type
  qRegisterMetaType<std::vector<Sync::MissingDataInfo> >("std::vector<Sync::MissingDataInfo>");
  qRegisterMetaType<size_t>("size_t");
  setupUi(this);
  m_session = time(NULL);
  m_scene = new DigestTreeScene(this);

  readSettings();

  updateLabels();

  lineEdit->setFocusPolicy(Qt::StrongFocus);

  treeViewer->setScene(m_scene);
  m_scene->plot("Empty");
  QRectF rect = m_scene->itemsBoundingRect();
  m_scene->setSceneRect(rect);

  listView->setStyleSheet("QListView { alternate-background-color: white; background: #F0F0F0; color: darkGreen; font: bold large; }");
  listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
  listView->setDragDropMode(QAbstractItemView::NoDragDrop);
  listView->setSelectionMode(QAbstractItemView::NoSelection);
  m_rosterModel = new QStringListModel(this);
  listView->setModel(m_rosterModel);

  refreshButton->setIcon(QIcon(QPixmap(":images/refresh.png")));
  reapButton->hide();

  createActions();
  createTrayIcon();
  m_timer = new QTimer(this);
  connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
  connect(setButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
  connect(treeButton, SIGNAL(pressed()), this, SLOT(treeButtonPressed()));
  connect(reapButton, SIGNAL(pressed()), this, SLOT(summonReaper()));
  connect(refreshButton, SIGNAL(pressed()), this, SLOT(updateLocalPrefix()));
  connect(this, SIGNAL(dataReceived(QString, const char *, size_t, bool, bool)), this, SLOT(processData(QString, const char *, size_t, bool, bool)));
  connect(this, SIGNAL(treeUpdated(const std::vector<Sync::MissingDataInfo>)), this, SLOT(processTreeUpdate(const std::vector<Sync::MissingDataInfo>)));
  connect(m_timer, SIGNAL(timeout()), this, SLOT(replot()));
  connect(m_scene, SIGNAL(replot()), this, SLOT(replot()));
  connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(showNormal()));
  connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
  connect(m_scene, SIGNAL(rosterChanged(QStringList)), this, SLOT(updateRosterList(QStringList)));

  initializeSync();

}

void
ChatDialog::initializeSync()
{
  // create sync socket
  if(!m_user.getChatroom().isEmpty() && !m_user.getNick().isEmpty()) {
    std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
    syncPrefix += "/";
    syncPrefix += m_user.getChatroom().toStdString();
    try
    {
      m_sock = new Sync::SyncAppSocket(syncPrefix,
                                       bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2),
                                       bind(&ChatDialog::processRemoveWrapper, this, _1));
      //QTimer::singleShot(100, this, SLOT(getLocalPrefix()));
      usleep(100000);
      if (!getLocalPrefix())
      {
        // if getLocalPrefix indicates no prefix change
        // this sock is going to be used
        QTimer::singleShot(600, this, SLOT(sendJoin()));
        m_timer->start(FRESHNESS * 1000);
        disableTreeDisplay();
        QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
        Sync::CcnxWrapperPtr handle = boost::make_shared<Sync::CcnxWrapper> ();
        handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
      }
      else
      {
        // this socket is going to be destroyed anyway
        // why bother doing the following steps

        // the same steps would be performed for another socket
        // in settingUpdated
      }
    }
    catch (Sync::CcnxOperationException ex)
    {
      QMessageBox::critical(this, tr("Chronos"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
      std::exit(1);
    }
  }
}

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

void
ChatDialog::sendLeave()
{
  SyncDemo::ChatMessage msg;
  formControlMessage(msg, SyncDemo::ChatMessage::LEAVE);
  sendMsg(msg);
  usleep(500000);
  m_sock->remove(m_user.getPrefix().toStdString());
  usleep(5000);
  m_joined = false;
#ifdef __DEBUG
  std::cout << "Sync REMOVE signal sent" << std::endl;
#endif
}

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

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::reap()
{
  if (m_zombieIndex < m_zombieList.size())
  {
    std::string prefix = m_zombieList.at(m_zombieIndex).toStdString();
    m_sock->remove(prefix);
    std::cout << "Reaped: prefix = " << prefix << std::endl;
    m_zombieIndex++;
    // reap again in 10 seconds
    QTimer::singleShot(10000, this, SLOT(reap()));
  }
}

void
ChatDialog::updateRosterList(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);
  }
}

void
ChatDialog::setVisible(bool visible)
{
  minimizeAction->setEnabled(visible);
  maximizeAction->setEnabled(!isMaximized());
  restoreAction->setEnabled(isMaximized() || !visible);
  QDialog::setVisible(visible);
}

void
ChatDialog::closeEvent(QCloseEvent *e)
{
  if (trayIcon->isVisible() && !m_minimaniho)
  {
    QMessageBox::information(this, tr("Chronos"),
			     tr("The program will keep running in the "
				"system tray. To terminate the program"
				"choose <b>Quit</b> in the context memu"
				"of the system tray entry."));
    hide();
    e->ignore();
    m_minimaniho = true;
    writeSettings();
  }
}

void
ChatDialog::changeEvent(QEvent *e)
{
  switch(e->type())
  {
  case QEvent::ActivationChange:
    if (isActiveWindow())
    {
      trayIcon->setIcon(QIcon(":/images/icon_small.png"));
    }
    break;
  default:
    break;
  }
}

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(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(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(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 = textEdit->verticalScrollBar();
  bar->setValue(bar->maximum());
}

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

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::processTreeUpdateWrapper(const std::vector<Sync::MissingDataInfo> v, Sync::SyncAppSocket *sock)
{
  emit treeUpdated(v);
#ifdef __DEBUG
  std::cout << "<<< Tree update signal emitted" << std::endl;
#endif
}

void
ChatDialog::processTreeUpdate(const std::vector<Sync::MissingDataInfo> v)
{
#ifdef __DEBUG
  std::cout << "<<< processing Tree Update" << std::endl;
#endif
  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->fetchRaw(v[i].prefix, seq, bind(&ChatDialog::processDataWrapper, this, _1, _2, _3), 2);
#ifdef __DEBUG
        std::cout << "<<< Fetching " << v[i].prefix << "/" <<seq.getSession() <<"/" << seq.getSeq() << std::endl;
#endif
      }
    }
    else
    {
        m_sock->fetchRaw(v[i].prefix, v[i].high, bind(&ChatDialog::processDataNoShowWrapper, this, _1, _2, _3), 2);
    }
  }

  // adjust the view
  fitView();

}

void
ChatDialog::processDataWrapper(std::string name, const char *buf, size_t len)
{
  char *tempBuf = new char[len];
  memcpy(tempBuf, buf, len);
  emit dataReceived(name.c_str(), tempBuf, len, true, false);
#ifdef __DEBUG
  std::cout <<"<<< " << name << " fetched" << std::endl;
#endif
}

void
ChatDialog::processDataNoShowWrapper(std::string name, const char *buf, size_t len)
{
  char *tempBuf = new char[len];
  memcpy(tempBuf, buf, len);
  emit dataReceived(name.c_str(), tempBuf, len, false, false);

  if (!m_historyInitialized)
  {
    fetchHistory(name);
    m_historyInitialized = true;
  }
}

void
ChatDialog::processDataHistoryWrapper(std::string name, const char *buf, size_t len)
{
  char *tempBuf = new char[len];
  memcpy(tempBuf, buf, len);
  emit dataReceived(name.c_str(), tempBuf, len, true, true);
}

void
ChatDialog::fetchHistory(std::string name)
{
  std::string nameWithoutSeq = name.substr(0, name.find_last_of('/'));
  std::string prefix = nameWithoutSeq.substr(0, nameWithoutSeq.find_last_of('/'));
  prefix += "/history";
  Sync::CcnxWrapperPtr handle = boost::make_shared<Sync::CcnxWrapper> ();
  QString randomString = getRandomString();
  for (int i = 0; i < MAX_HISTORY_ENTRY; i++)
  {
    QString interest = QString("%1/%2/%3").arg(prefix.c_str()).arg(randomString).arg(i);
    handle->sendInterest(interest.toStdString(), bind(&ChatDialog::processDataHistoryWrapper, this, _1, _2, _3));
  }
}

void
ChatDialog::respondHistoryRequest(std::string interest)
{
  std::string seqStr = interest.substr(interest.find_last_of('/') + 1);
  int seq = boost::lexical_cast<int>(seqStr);
  if (seq >= 0 && seq < m_history.size())
  {
    Sync::CcnxWrapperPtr handle = boost::make_shared<Sync::CcnxWrapper> ();
    SyncDemo::ChatMessage msg = m_history.at(seq);
    size_t size = msg.ByteSize();
    char *buf = new char[size];
    msg.SerializeToArray(buf, size);
    handle->publishRawData(interest, buf, size, 1);
    delete buf;
  }
}

void
ChatDialog::processData(QString name, const char *buf, size_t len, bool show, bool isHistory)
{
  SyncDemo::ChatMessage msg;
  bool corrupted = false;
  if (!msg.ParseFromArray(buf, len))
  {
    std::cerr << "Errrrr.. Can not parse msg with name: " << name.toStdString() << ". what is happening?" << std::endl;
    // 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;
  }

  delete [] buf;
  buf = NULL;

  // 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 stdStrName = name.toStdString();
    std::string stdStrNameWithoutSeq = stdStrName.substr(0, stdStrName.find_last_of('/'));
    std::string prefix = stdStrNameWithoutSeq.substr(0, stdStrNameWithoutSeq.find_last_of('/'));
#ifdef __DEBUG
    std::cout <<"<<< updating scene for" << prefix << ": " << msg.from()  << std::endl;
#endif
    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::processRemoveWrapper(std::string prefix)
{
#ifdef __DEBUG
  std::cout << "Sync REMOVE signal received for prefix: " << prefix << std::endl;
#endif
  //emit removeReceived(prefix.c_str());
}

void
ChatDialog::processRemove(QString prefix)
{
#ifdef __DEBUG
  std::cout << "<<< remove node for prefix" << prefix.toStdString() << std::endl;
#endif
  bool removed = m_scene->removeNode(prefix);
  if (removed)
  {
    boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
    m_scene->plot(m_sock->getRootDigest().c_str());
  }
}

void
ChatDialog::formChatMessage(const QString &text, SyncDemo::ChatMessage &msg) {
  msg.set_from(m_user.getNick().toStdString());
  msg.set_to(m_user.getChatroom().toStdString());
  msg.set_data(text.toUtf8().constData());
  time_t seconds = time(NULL);
  msg.set_timestamp(seconds);
  msg.set_type(SyncDemo::ChatMessage::CHAT);
}

void
ChatDialog::formControlMessage(SyncDemo::ChatMessage &msg, SyncDemo::ChatMessage::ChatMessageType type)
{
  msg.set_from(m_user.getNick().toStdString());
  msg.set_to(m_user.getChatroom().toStdString());
  time_t seconds = time(NULL);
  msg.set_timestamp(seconds);
  msg.set_type(type);
}

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

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

bool
ChatDialog::getLocalPrefix()
{
//   /*
//    * this method tries to use ccncat
//    * however, it does not work in Mac OS X app bundle
//    * it works well in command line though
//    */

//   std::string cmd = CCN_EXEC;
//   cmd += " -c -v ";
//   cmd += LOCAL_PREFIX_QUERY;
//   QString localPrefix;
// #define MAX_PREFIX_LEN 100
//   FILE *fp = popen(cmd.c_str(), "r");
//   if (fp != NULL)
//   {
//     char prefix[MAX_PREFIX_LEN];
//     if (fgets(prefix, MAX_PREFIX_LEN, fp) != NULL)
//     {
//       localPrefix = prefix;
//       localPrefix.remove('\n');
//     }
//     else
//     {
//       localPrefix = DEFAULT_LOCAL_PREFIX;
//     }
//     pclose(fp);
//   }
//   else
//   {
//     localPrefix = DEFAULT_LOCAL_PREFIX;
//   }
//   return localPrefix;
  std::cerr << "trying to get local prefix" << std::endl;

  if (m_sock != NULL)
  {
    QString originPrefix = QString::fromStdString (m_sock->GetLocalPrefix()).trimmed ();
    std::cerr << "got: " << originPrefix.toStdString () << std::endl;

    if (originPrefix != "" && m_user.getOriginPrefix () != originPrefix)
    {
      emit settingUpdated(m_user.getNick (), m_user.getChatroom (), originPrefix);
      // prefix updated
      return true;
    }
  }

  // prefix not changed
  return false;
}

void
ChatDialog::updateLocalPrefix()
{
  getLocalPrefix();
}

bool
ChatDialog::readSettings()
{
  QSettings s(ORGANIZATION, APPLICATION);
  QString nick = s.value("nick", "").toString();
  QString chatroom = s.value("chatroom", "").toString();
  // QString originPrefix = s.value("originPrefix", "").toString();

  // Sync::CcnxWrapperPtr wrapper = Sync::CcnxWrapper::Create ();
  // QString originPrefix = QString::fromStdString (wrapper->getLocalPrefix());
  // Sync::CcnxWrapper::Destroy ();

  QString originPrefix = DEFAULT_LOCAL_PREFIX;

  m_minimaniho = s.value("minimaniho", false).toBool();
  if (nick == "" || chatroom == "" || originPrefix == "") {
    m_user.setOriginPrefix(DEFAULT_LOCAL_PREFIX);
    m_user.setChatroom("retreat2012");
    QTimer::singleShot(500, this, SLOT(buttonPressed()));
    return false;
  }
  else {
    m_user.setNick(nick);
    m_user.setChatroom(chatroom);
    m_user.setOriginPrefix(originPrefix);
    m_user.setPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
    m_scene->setCurrentPrefix(originPrefix + "/" + chatroom + "/" + getRandomString());
    return true;
  }

//  QTimer::singleShot(500, this, SLOT(buttonPressed()));
 // return false;
}

void
ChatDialog::writeSettings()
{
  QSettings s(ORGANIZATION, APPLICATION);
  s.setValue("nick", m_user.getNick());
  s.setValue("chatroom", m_user.getChatroom());
  //s.setValue("originPrefix", m_user.getOriginPrefix());
  s.setValue("minimaniho", m_minimaniho);
}

void
ChatDialog::updateLabels()
{
  QString settingDisp = QString("Chatroom: %1").arg(m_user.getChatroom());
  infoLabel->setStyleSheet("QLabel {color: #630; font-size: 16px; font: bold \"Verdana\";}");
  infoLabel->setText(settingDisp);
  QString prefixDisp;
  if (m_user.getPrefix().startsWith(DEFAULT_LOCAL_PREFIX))
  {
    prefixDisp = QString("<Warning: no connection to hub or hub does not support prefix autoconfig.>\n <Prefix = %1>").arg(m_user.getPrefix());
    prefixLabel->setStyleSheet("QLabel {color: red; font-size: 12px; font: bold \"Verdana\";}");
  }
  else
  {
    prefixDisp = QString("<Prefix = %1>").arg(m_user.getPrefix());
    prefixLabel->setStyleSheet("QLabel {color: Green; font-size: 12px; font: bold \"Verdana\";}");
  }
  prefixLabel->setText(prefixDisp);
}

void
ChatDialog::returnPressed()
{
  QString text = lineEdit->text();
  if (text.isEmpty())
    return;

  lineEdit->clear();

  if (text.startsWith("boruoboluomi"))
  {
    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::sendMsg(SyncDemo::ChatMessage &msg)
{
  // send msg
  size_t size = msg.ByteSize();
  char *buf = new char[size];
  msg.SerializeToArray(buf, size);
  if (!msg.IsInitialized())
  {
    std::cerr << "Errrrr.. msg was not probally initialized "<<__FILE__ <<":"<<__LINE__<<". what is happening?" << std::endl;
    abort();
  }
  m_sock->publishRaw(m_user.getPrefix().toStdString(), m_session, buf, size, FRESHNESS);

  delete buf;

  m_lastMsgTime = time(NULL);

  int nextSequence = m_sock->getNextSeq(m_user.getPrefix().toStdString(), m_session);
  Sync::MissingDataInfo mdi = {m_user.getPrefix().toStdString(), Sync::SeqNo(0), Sync::SeqNo(nextSequence - 1)};
  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(m_user.getPrefix(), m_user.getNick());
  }
}

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()
{
  time_t now = time(NULL);
  int elapsed = now - m_lastMsgTime;
  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::buttonPressed()
{
  if (m_sock != NULL)
  {
    Sync::SyncLogic &logic = m_sock->getLogic ();
    logic.printState ();
  }

  SettingDialog dialog(this, m_user.getNick(), m_user.getChatroom(), m_user.getOriginPrefix());
  connect(&dialog, SIGNAL(updated(QString, QString, QString)), this, SLOT(settingUpdated(QString, QString, QString)));
  dialog.exec();
  QTimer::singleShot(100, this, SLOT(checkSetting()));
}

void ChatDialog::treeButtonPressed()
{
  if (treeViewer->isVisible())
  {
    treeViewer->hide();
    treeButton->setText("Show Sync Tree");
  }
  else
  {
    treeViewer->show();
    treeButton->setText("Hide Sync Tree");
  }

  fitView();
}

void ChatDialog::enableTreeDisplay()
{
  treeButton->setEnabled(true);
  treeViewer->show();
  fitView();
}

void ChatDialog::disableTreeDisplay()
{
  treeButton->setEnabled(false);
  treeViewer->hide();
  fitView();
}

void
ChatDialog::checkSetting()
{
  if (m_user.getNick().isEmpty() || m_user.getChatroom().isEmpty() || m_user.getOriginPrefix().isEmpty())
  {
    buttonPressed();
  }

}

void
ChatDialog::settingUpdated(QString nick, QString chatroom, QString originPrefix)
{
  QString randString = getRandomString();
  bool needWrite = false;
  bool needFresh = false;
  if (!nick.isEmpty() && nick != m_user.getNick()) {
    m_user.setNick(nick);
    needWrite = true;
  }
  QString oldPrefix = m_user.getPrefix();
  if (!originPrefix.isEmpty() && originPrefix != m_user.getOriginPrefix()) {
    m_user.setOriginPrefix(originPrefix);
    m_user.setPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
    m_scene->setCurrentPrefix(originPrefix + "/" + m_user.getChatroom() + "/" + randString);
    needWrite = true;
    needFresh = true;
  }
  if (!chatroom.isEmpty() && chatroom != m_user.getChatroom()) {
    m_user.setChatroom(chatroom);
    m_user.setPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
    m_scene->setCurrentPrefix(m_user.getOriginPrefix() + "/" + chatroom + "/" + randString);
    needWrite = true;
    needFresh = true;
  }

  if (needWrite) {
    writeSettings();
    updateLabels();
  }

  if (needFresh && m_sock != NULL)
  {

    {
      boost::recursive_mutex::scoped_lock lock(m_sceneMutex);
      m_scene->clearAll();
      m_scene->plot("Empty");
    }

    textEdit->clear();

    // keep the new prefix
    QString newPrefix = m_user.getPrefix();
    // send leave for the old
    m_user.setPrefix(oldPrefix);
    // there is no point to send leave if we haven't joined yet
    if (m_joined)
    {
      sendLeave();
    }
    // resume new prefix
    m_user.setPrefix(newPrefix);
    // Sync::CcnxWrapperPtr handle = Sync::CcnxWrapper::Create();
    // handle->clearInterestFilter(oldPrefix.toStdString());
    m_history.clear();
    m_historyInitialized = false;
    delete m_sock;
    m_sock = NULL;

    std::string syncPrefix = BROADCAST_PREFIX_FOR_SYNC_DEMO;
    syncPrefix += "/";
    syncPrefix += m_user.getChatroom().toStdString();
    try
    {
      usleep(100000);
      m_sock = new Sync::SyncAppSocket(syncPrefix, bind(&ChatDialog::processTreeUpdateWrapper, this, _1, _2), bind(&ChatDialog::processRemoveWrapper, this, _1));
      usleep(100000);
      Sync::CcnxWrapperPtr handle = boost::make_shared<Sync::CcnxWrapper> ();
      handle->setInterestFilter(m_user.getPrefix().toStdString(), bind(&ChatDialog::respondHistoryRequest, this, _1));
      QTimer::singleShot(600, this, SLOT(sendJoin()));
      m_timer->start(FRESHNESS * 1000);
      disableTreeDisplay();
      QTimer::singleShot(2200, this, SLOT(enableTreeDisplay()));
    }
    catch (Sync::CcnxOperationException ex)
    {
      QMessageBox::critical(this, tr("Chronos"), tr("Canno connect to ccnd.\n Have you started your ccnd?"), QMessageBox::Ok);
      std::exit(1);
    }


  }
  else if (needFresh && m_sock == NULL)
  {
    m_history.clear();
    m_historyInitialized = false;
    initializeSync();
  }
  else if (m_sock == NULL)
  {
    initializeSync();
  }
  else
  {
#ifdef __DEBUG
    std::cout << "Just changing nicks, we're good. " << std::endl;
#endif
  }

  fitView();
}

void
ChatDialog::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
  switch (reason)
  {
  case QSystemTrayIcon::Trigger:
  case QSystemTrayIcon::DoubleClick:
    break;
  case QSystemTrayIcon::MiddleClick:
    // showMessage();
    break;
  default:;
  }
}

void
ChatDialog::showMessage(QString from, QString data)
{
  //  std::cout <<"Showing Message: " << from.toStdString() << ": " << data.toStdString() << std::endl;
  if (!isActiveWindow())
  {
    trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(m_user.getChatroom()), QString("<%1>: %2").arg(from).arg(data), QSystemTrayIcon::Information, 20000);
    trayIcon->setIcon(QIcon(":/images/note.png"));
  }
}

void
ChatDialog::messageClicked()
{
  this->showMaximized();
}

void
ChatDialog::createActions()
{
  minimizeAction = new QAction(tr("Mi&nimize"), this);
  connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));

  maximizeAction = new QAction(tr("Ma&ximize"), this);
  connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));

  restoreAction = new QAction(tr("&Restore"), this);
  connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));

  quitAction = new QAction(tr("Quit"), this);
  connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void
ChatDialog::createTrayIcon()
{
  trayIconMenu = new QMenu(this);
  trayIconMenu->addAction(minimizeAction);
  trayIconMenu->addAction(maximizeAction);
  trayIconMenu->addAction(restoreAction);
  trayIconMenu->addSeparator();
  trayIconMenu->addAction(quitAction);

  trayIcon = new QSystemTrayIcon(this);
  trayIcon->setContextMenu(trayIconMenu);

  QIcon icon(":/images/icon_small.png");
  trayIcon->setIcon(icon);
  setWindowIcon(icon);
  trayIcon->setToolTip("Chronos System Tray Icon");
  trayIcon->setVisible(true);
}

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

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

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