/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013, Regents of the University of California
 *                     Yingdi Yu
 *
 * BSD license, See the LICENSE file for more information
 *
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 */

#include <QApplication>
#include <QMessageBox>
#include <QDir>
#include <QTimer>
#include "controller.h"

#ifndef Q_MOC_RUN
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <ndn-cpp-dev/util/random.hpp>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/files.h>
#include <cryptopp/filters.h>
#include "config.pb.h"
#include "endorse-info.pb.h"
#include "logging.h"
#endif

INIT_LOGGER("chronos.Controller");

using namespace ndn;

Q_DECLARE_METATYPE(ndn::Name)
Q_DECLARE_METATYPE(ndn::IdentityCertificate)
Q_DECLARE_METATYPE(chronos::EndorseInfo)
Q_DECLARE_METATYPE(ndn::Interest)
Q_DECLARE_METATYPE(size_t)

namespace chronos {

static const uint8_t ROUTING_PREFIX_SEPARATOR[2] = {0xF0, 0x2E};

// constructor & destructor
Controller::Controller(shared_ptr<Face> face,
		       QWidget* parent)
  : QDialog(parent)
  , m_face(face)
  , m_invitationListenerId(0)
  , m_contactManager(m_face)
  , m_settingDialog(new SettingDialog)
  , m_startChatDialog(new StartChatDialog)
  , m_profileEditor(new ProfileEditor)
  , m_invitationDialog(new InvitationDialog)
  , m_contactPanel(new ContactPanel)
  , m_browseContactDialog(new BrowseContactDialog)
  , m_addContactPanel(new AddContactPanel)
{
  qRegisterMetaType<ndn::Name>("ndn.Name");
  qRegisterMetaType<ndn::IdentityCertificate>("ndn.IdentityCertificate");
  qRegisterMetaType<chronos::EndorseInfo>("chronos.EndorseInfo");
  qRegisterMetaType<ndn::Interest>("ndn.Interest");
  qRegisterMetaType<size_t>("size_t");

  connect(this, SIGNAL(localPrefixUpdated(const QString&)),
          this, SLOT(onLocalPrefixUpdated(const QString&)));
  connect(this, SIGNAL(invitationInterest(const ndn::Name&, const ndn::Interest&, size_t)),
          this, SLOT(onInvitationInterest(const ndn::Name&, const ndn::Interest&, size_t)));

  // Connection to ContactManager
  connect(this, SIGNAL(identityUpdated(const QString&)),
          &m_contactManager, SLOT(onIdentityUpdated(const QString&)));
  connect(&m_contactManager, SIGNAL(warning(const QString&)),
          this, SLOT(onWarning(const QString&)));
  connect(this, SIGNAL(refreshBrowseContact()),
          &m_contactManager, SLOT(onRefreshBrowseContact()));
  connect(&m_contactManager, SIGNAL(contactInfoFetchFailed(const QString&)),
          this, SLOT(onWarning(const QString&)));
  connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
          this, SLOT(onContactIdListReady(const QStringList&)));

  // Connection to SettingDialog
  connect(this, SIGNAL(identityUpdated(const QString&)),
          m_settingDialog, SLOT(onIdentityUpdated(const QString&)));
  connect(m_settingDialog, SIGNAL(identityUpdated(const QString&)),
          this, SLOT(onIdentityUpdated(const QString&)));
  connect(m_settingDialog, SIGNAL(nickUpdated(const QString&)),
          this, SLOT(onNickUpdated(const QString&)));

  // Connection to ProfileEditor
  connect(this, SIGNAL(closeDBModule()),
          m_profileEditor, SLOT(onCloseDBModule()));
  connect(this, SIGNAL(identityUpdated(const QString&)),
          m_profileEditor, SLOT(onIdentityUpdated(const QString&)));
  connect(m_profileEditor, SIGNAL(updateProfile()),
          &m_contactManager, SLOT(onUpdateProfile()));

  // Connection to StartChatDialog
  connect(m_startChatDialog, SIGNAL(startChatroom(const QString&, bool)),
          this, SLOT(onStartChatroom(const QString&, bool)));

  // Connection to InvitationDialog
  connect(m_invitationDialog, SIGNAL(invitationResponded(const ndn::Name&, bool)),
          this, SLOT(onInvitationResponded(const ndn::Name&, bool)));

  // Connection to AddContactPanel
  connect(m_addContactPanel, SIGNAL(fetchInfo(const QString&)),
          &m_contactManager, SLOT(onFetchContactInfo(const QString&)));
  connect(m_addContactPanel, SIGNAL(addContact(const QString&)),
          &m_contactManager, SLOT(onAddFetchedContact(const QString&)));
  connect(&m_contactManager, SIGNAL(contactEndorseInfoReady(const chronos::EndorseInfo&)),
          m_addContactPanel, SLOT(onContactEndorseInfoReady(const chronos::EndorseInfo&)));


  // Connection to BrowseContactDialog
  connect(m_browseContactDialog, SIGNAL(directAddClicked()),
          this, SLOT(onDirectAdd()));
  connect(m_browseContactDialog, SIGNAL(fetchIdCert(const QString&)),
          &m_contactManager, SLOT(onFetchIdCert(const QString&)));
  connect(m_browseContactDialog, SIGNAL(addContact(const QString&)),
          &m_contactManager, SLOT(onAddFetchedContactIdCert(const QString&)));
  connect(&m_contactManager, SIGNAL(idCertNameListReady(const QStringList&)),
          m_browseContactDialog, SLOT(onIdCertNameListReady(const QStringList&)));
  connect(&m_contactManager, SIGNAL(nameListReady(const QStringList&)),
          m_browseContactDialog, SLOT(onNameListReady(const QStringList&)));
  connect(&m_contactManager, SIGNAL(idCertReady(const ndn::IdentityCertificate&)),
          m_browseContactDialog, SLOT(onIdCertReady(const ndn::IdentityCertificate&)));

  // Connection to ContactPanel
  connect(m_contactPanel, SIGNAL(waitForContactList()),
          &m_contactManager, SLOT(onWaitForContactList()));
  connect(m_contactPanel, SIGNAL(waitForContactInfo(const QString&)),
          &m_contactManager, SLOT(onWaitForContactInfo(const QString&)));
  connect(m_contactPanel, SIGNAL(removeContact(const QString&)),
          &m_contactManager, SLOT(onRemoveContact(const QString&)));
  connect(m_contactPanel, SIGNAL(updateAlias(const QString&, const QString&)),
          &m_contactManager, SLOT(onUpdateAlias(const QString&, const QString&)));
  connect(m_contactPanel, SIGNAL(updateIsIntroducer(const QString&, bool)),
          &m_contactManager, SLOT(onUpdateIsIntroducer(const QString&, bool)));
  connect(m_contactPanel, SIGNAL(updateEndorseCertificate(const QString&)),
          &m_contactManager, SLOT(onUpdateEndorseCertificate(const QString&)));
  connect(m_contactPanel, SIGNAL(warning(const QString&)),
          this, SLOT(onWarning(const QString&)));
  connect(this, SIGNAL(closeDBModule()),
          m_contactPanel, SLOT(onCloseDBModule()));
  connect(this, SIGNAL(identityUpdated(const QString&)),
          m_contactPanel, SLOT(onIdentityUpdated(const QString&)));
  connect(&m_contactManager, SIGNAL(contactAliasListReady(const QStringList&)),
          m_contactPanel, SLOT(onContactAliasListReady(const QStringList&)));
  connect(&m_contactManager, SIGNAL(contactIdListReady(const QStringList&)),
          m_contactPanel, SLOT(onContactIdListReady(const QStringList&)));
  connect(&m_contactManager, SIGNAL(contactInfoReady(const QString&, const QString&, const QString&, bool)),
          m_contactPanel, SLOT(onContactInfoReady(const QString&, const QString&, const QString&, bool)));

  initialize();

  createTrayIcon();

  onUpdateLocalPrefixAction();
}
  
Controller::~Controller()
{
  saveConf();
}

// public methods


// private methods
std::string
Controller::getDBName()
{
  std::string dbName("chronos-");

  std::stringstream ss;
  {
    using namespace CryptoPP;

    SHA256 hash;
    StringSource(m_identity.wireEncode().wire(), m_identity.wireEncode().size(), true,
                 new HashFilter(hash, new HexEncoder(new FileSink(ss), false)));
  }
  dbName.append(ss.str()).append(".db");

  return dbName;
}

void
Controller::openDB()
{
  m_db = QSqlDatabase::addDatabase("QSQLITE");
  QString path = (QDir::home().path());
  path.append(QDir::separator()).append(".chronos").append(QDir::separator()).append(getDBName().c_str());
  m_db.setDatabaseName(path);
  bool ok = m_db.open();

  _LOG_DEBUG("DB opened: " << std::boolalpha << ok );
}

void
Controller::initialize()
{
  loadConf();
  
  m_keyChain.createIdentity(m_identity);

  openDB();

  emit identityUpdated(QString(m_identity.toUri().c_str()));

  setInvitationListener();
}

void
Controller::setInvitationListener()
{
  if(m_invitationListenerId != 0)
    m_face->unsetInterestFilter(m_invitationListenerId);
  
  Name invitationPrefix;
  Name routingPrefix = getInvitationRoutingPrefix();
  size_t offset = 0;
  if(!routingPrefix.isPrefixOf(m_identity))
    {
      invitationPrefix.append(routingPrefix).append(ROUTING_PREFIX_SEPARATOR, 2);
      offset = routingPrefix.size() + 1;
    }
  invitationPrefix.append(m_identity).append("CHRONOCHAT-INVITATION");

  m_invitationListenerId = m_face->setInterestFilter(invitationPrefix, 
                                                     bind(&Controller::onInvitationInterestWrapper, this, _1, _2, offset),
                                                     bind(&Controller::onInvitationRegisterFailed, this, _1, _2));
}

void
Controller::loadConf()
{
  namespace fs = boost::filesystem;

  fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
  fs::create_directories (chronosDir);

  std::ifstream is((chronosDir / "config").c_str ());
  ChronoChat::Conf conf;
  if(conf.ParseFromIstream(&is))
    {
      m_identity.clear();
      m_identity.append(conf.identity());
      if(conf.has_nick())
        m_nick = conf.nick();
      else
        m_nick = m_identity.get(-1).toUri();
    }
  else
    {
      m_identity.clear();
      // TODO: change below to system default;
      m_identity.append("chronochat-tmp-identity")
        .append(boost::lexical_cast<std::string>(random::generateWord64()));
      
      m_nick = m_identity.get(-1).toUri();
    }
}

void 
Controller::saveConf()
{
  namespace fs = boost::filesystem;

  fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
  fs::create_directories (chronosDir);

  std::ofstream os((chronosDir / "config").c_str ());
  ChronoChat::Conf conf;
  conf.set_identity(m_identity.toUri());
  if(!m_nick.empty())
    conf.set_nick(m_nick);
  conf.SerializeToOstream(&os);

  os.close();
}

void
Controller::createActions()
{
  m_startChatroom = new QAction(tr("Start new chat"), this);
  connect(m_startChatroom, SIGNAL(triggered()), this, SLOT(onStartChatAction()));

  m_settingsAction = new QAction(tr("Settings"), this);
  connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(onSettingsAction()));

  m_editProfileAction = new QAction(tr("Edit profile"), this);
  connect(m_editProfileAction, SIGNAL(triggered()), this, SLOT(onProfileEditorAction()));

  m_contactListAction = new QAction(tr("Contact List"), this);
  connect(m_contactListAction, SIGNAL(triggered()), this, SLOT(onContactListAction()));

  m_addContactAction = new QAction(tr("Add contact"), this);
  connect(m_addContactAction, SIGNAL(triggered()), this, SLOT(onAddContactAction()));

  m_updateLocalPrefixAction = new QAction(tr("Update local prefix"), this);
  connect(m_updateLocalPrefixAction, SIGNAL(triggered()), this, SLOT(onUpdateLocalPrefixAction()));

  m_minimizeAction = new QAction(tr("Mi&nimize"), this);
  connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(onMinimizeAction()));

  m_quitAction = new QAction(tr("Quit"), this);
  connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuitAction()));
}

void
Controller::createTrayIcon()
{
  createActions();

  m_trayIconMenu = new QMenu(this);
  m_trayIconMenu->addAction(m_startChatroom);
  m_trayIconMenu->addSeparator();
  m_trayIconMenu->addAction(m_settingsAction);
  m_trayIconMenu->addAction(m_editProfileAction);
  m_trayIconMenu->addSeparator();
  m_trayIconMenu->addAction(m_contactListAction);
  m_trayIconMenu->addAction(m_addContactAction);
  m_trayIconMenu->addSeparator();
  m_trayIconMenu->addAction(m_updateLocalPrefixAction);
  m_trayIconMenu->addSeparator();
  m_trayIconMenu->addAction(m_minimizeAction);
  m_closeMenu = m_trayIconMenu->addMenu("Close chatroom");
  m_closeMenu->setEnabled(false);
  m_trayIconMenu->addSeparator();
  m_trayIconMenu->addAction(m_quitAction);

  m_trayIcon = new QSystemTrayIcon(this);
  m_trayIcon->setContextMenu(m_trayIconMenu);

  m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
  m_trayIcon->setToolTip("ChronoChat System Tray Icon");
  m_trayIcon->setVisible(true);
}

void
Controller::updateMenu()
{
  QMenu* menu = new QMenu(this);
  QMenu* closeMenu = 0;
  
  menu->addAction(m_startChatroom);
  menu->addSeparator();
  menu->addAction(m_settingsAction);
  menu->addAction(m_editProfileAction);
  menu->addSeparator();
  menu->addAction(m_contactListAction);
  menu->addAction(m_addContactAction);
  menu->addSeparator();
  {
    ChatActionList::const_iterator it = m_chatActionList.begin();
    ChatActionList::const_iterator end = m_chatActionList.end();
    if(it != end)
      {
        for(; it != end; it++)
          menu->addAction(it->second);
        menu->addSeparator();
      }
  }
  menu->addAction(m_updateLocalPrefixAction);
  menu->addSeparator();
  menu->addAction(m_minimizeAction);
  closeMenu = menu->addMenu("Close chatroom");
  {
    ChatActionList::const_iterator it = m_closeActionList.begin();
    ChatActionList::const_iterator end = m_closeActionList.end();
    if(it == end)
      {
        closeMenu->setEnabled(false);
      }
    else
      {
        for(; it != end; it++)
          closeMenu->addAction(it->second);
      }
  }
  menu->addSeparator();
  menu->addAction(m_quitAction);
  
  m_trayIcon->setContextMenu(menu);
  delete m_trayIconMenu;
  m_trayIconMenu = menu;
  m_closeMenu = closeMenu;
}

void
Controller::onLocalPrefix(const Interest& interest, Data& data)
{
  QString localPrefixStr = QString::fromUtf8
    (reinterpret_cast<const char*>(data.getContent().value()), data.getContent().value_size())
    .trimmed();

  Name localPrefix(localPrefixStr.toStdString());
  if(m_localPrefix.empty() || m_localPrefix != localPrefix)
    emit localPrefixUpdated(localPrefixStr);
}

void
Controller::onLocalPrefixTimeout(const Interest& interest)
{
  QString localPrefixStr("/private/local");

  Name localPrefix(localPrefixStr.toStdString());
  if(m_localPrefix.empty() || m_localPrefix != localPrefix)
    emit localPrefixUpdated(localPrefixStr);
}

void
Controller::onInvitationInterestWrapper(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
{
  emit invitationInterest(prefix, interest, routingPrefixOffset);
}

void
Controller::onInvitationRegisterFailed(const Name& prefix, const std::string& failInfo)
{
  _LOG_DEBUG("Controller::onInvitationRegisterFailed: " << failInfo);
}

void
Controller::onInvitationValidated(const shared_ptr<const Interest>& interest)
{
  Invitation invitation(interest->getName());
  std::string alias = invitation.getInviterCertificate().getPublicKeyName().getPrefix(-1).toUri(); // Should be obtained via a method of ContactManager.

  m_invitationDialog->setInvitation(alias, invitation.getChatroom(), interest->getName());
  m_invitationDialog->show();
}

void
Controller::onInvitationValidationFailed(const shared_ptr<const Interest>& interest, std::string failureInfo)
{
  _LOG_DEBUG("Invitation: " << interest->getName() << " cannot not be validated due to: " << failureInfo);
}

std::string
Controller::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));
    
  }
  // for(int i = 0; i < 8; i++)
  //   {
  //     uint32_t t = r & mask;
  //     if(t < 10)
  //       ss << static_cast<char>(t + 0x30);
  //     else
  //       ss << static_cast<char>(t + 0x57);
  //     r = r >> 4;
  //   }

  return ss.str();
}

ndn::Name
Controller::getInvitationRoutingPrefix()
{
  return Name("/ndn/broadcast");
}

void
Controller::addChatDialog(const QString& chatroomName, ChatDialog* chatDialog)
{
  m_chatDialogList[chatroomName.toStdString()] = chatDialog;
  connect(chatDialog, SIGNAL(closeChatDialog(const QString&)),
          this, SLOT(onRemoveChatDialog(const QString&)));
  connect(chatDialog, SIGNAL(showChatMessage(const QString&, const QString&, const QString&)),
          this, SLOT(onShowChatMessage(const QString&, const QString&, const QString&)));
  connect(chatDialog, SIGNAL(resetIcon()),
          this, SLOT(onResetIcon()));
  connect(this, SIGNAL(localPrefixUpdated(const QString&)),
          chatDialog, SLOT(onLocalPrefixUpdated(const QString&)));

  QAction* chatAction = new QAction(chatroomName, this);
  m_chatActionList[chatroomName.toStdString()] = chatAction;
  connect(chatAction, SIGNAL(triggered()), chatDialog, SLOT(raise()));

  QAction* closeAction = new QAction(chatroomName, this);
  m_closeActionList[chatroomName.toStdString()] = closeAction;
  connect(closeAction, SIGNAL(triggered()), chatDialog, SLOT(onClose()));

  updateMenu();
}

// private slots:
void
Controller::onIdentityUpdated(const QString& identity)
{
  Name identityName(identity.toStdString());

  while(!m_chatDialogList.empty())
    {
      ChatDialogList::const_iterator it = m_chatDialogList.begin();
      onRemoveChatDialog(QString::fromStdString(it->first));
    }

  m_identity = identityName;
  m_keyChain.createIdentity(m_identity);
  setInvitationListener();

  emit closeDBModule();
  
  QTimer::singleShot(500, this, SLOT(onIdentityUpdatedContinued()));

}

void
Controller::onIdentityUpdatedContinued()
{
  QString connection = m_db.connectionName();
  // _LOG_DEBUG("connection name: " << connection.toStdString());
  QSqlDatabase::removeDatabase(connection);
  m_db.close();
  
  openDB();

  emit identityUpdated(QString(m_identity.toUri().c_str()));
}

void
Controller::onContactIdListReady(const QStringList& list)
{
  ContactList contactList;

  m_contactManager.getContactList(contactList);
  m_validator.cleanTrustAnchor();

  ContactList::const_iterator it  = contactList.begin();
  ContactList::const_iterator end = contactList.end();

  for(; it != end; it++)
    m_validator.addTrustAnchor((*it)->getPublicKeyName(), (*it)->getPublicKey());

}

void
Controller::onNickUpdated(const QString& nick)
{
  m_nick = nick.toStdString();
}

void
Controller::onLocalPrefixUpdated(const QString& localPrefix)
{
  m_localPrefix = Name(localPrefix.toStdString());
}

void
Controller::onStartChatAction()
{
  std::string chatroom = "chatroom-" + getRandomString();

  m_startChatDialog->setChatroom(chatroom);
  m_startChatDialog->show();
  m_startChatDialog->raise();
}

void
Controller::onSettingsAction()
{
  m_settingDialog->setNick(QString(m_nick.c_str()));
  m_settingDialog->show();
  m_settingDialog->raise();
}

void
Controller::onProfileEditorAction()
{
  m_profileEditor->show();
  m_profileEditor->raise();
}

void
Controller::onAddContactAction()
{
  emit refreshBrowseContact();
  m_browseContactDialog->show();
  m_browseContactDialog->raise();
}

void
Controller::onContactListAction()
{
  m_contactPanel->show();
  m_contactPanel->raise();
}

void
Controller::onDirectAdd()
{
  m_addContactPanel->show();
  m_addContactPanel->raise();
}

void
Controller::onUpdateLocalPrefixAction()
{
  // Name interestName();
  Interest interest("/local/ndn/prefix");
  interest.setInterestLifetime(1000);
  interest.setMustBeFresh(true);

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

void
Controller::onMinimizeAction()
{
  m_settingDialog->hide();
  m_startChatDialog->hide();
  m_profileEditor->hide();
  m_invitationDialog->hide();
  m_addContactPanel->hide();

  ChatDialogList::iterator it = m_chatDialogList.begin();
  ChatDialogList::iterator end = m_chatDialogList.end();
  for(; it != end; it++)
    it->second->hide();
}

void
Controller::onQuitAction()
{
  while(!m_chatDialogList.empty())
    {
      ChatDialogList::const_iterator it = m_chatDialogList.begin();
      onRemoveChatDialog(QString::fromStdString(it->first));
    }

  if(m_invitationListenerId != 0)
    m_face->unsetInterestFilter(m_invitationListenerId);

  delete m_settingDialog;
  delete m_startChatDialog;
  delete m_profileEditor;
  delete m_invitationDialog;
  delete m_browseContactDialog;
  delete m_addContactPanel;

  m_face->shutdown();

  QApplication::quit();
}

void
Controller::onStartChatroom(const QString& chatroomName, bool secured)
{
  Name chatroomPrefix;
  chatroomPrefix.append("ndn")
    .append("broadcast")
    .append("ChronoChat")
    .append(chatroomName.toStdString());

  // check if the chatroom exists
  if(m_chatDialogList.find(chatroomName.toStdString()) != m_chatDialogList.end())
    {
      QMessageBox::information(this, tr("ChronoChat"),
                               tr("You are creating an existing chatroom."
                                  "You can check it in the context memu."));
      return;
    }

  // TODO: We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
  shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
  ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, secured);

  addChatDialog(chatroomName, chatDialog);  
  chatDialog->show();
}

void
Controller::onInvitationResponded(const Name& invitationName, bool accepted)
{
  Data response;
  shared_ptr<IdentityCertificate> chatroomCert;

  // generate reply;
  if(accepted)
    {
      Name responseName = invitationName;
      responseName.append(m_localPrefix.wireEncode());

      response.setName(responseName);

      // We should create a particular certificate for this chatroom, but let's use default one for now.
      chatroomCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));

      response.setContent(chatroomCert->wireEncode());
      response.setFreshnessPeriod(1000);      
    }
  else
    {
      response.setName(invitationName);
      response.setFreshnessPeriod(1000);
    }
  m_keyChain.signByIdentity(response, m_identity);
  
  // Check if we need a wrapper
  Name invitationRoutingPrefix = getInvitationRoutingPrefix();
  if(invitationRoutingPrefix.isPrefixOf(m_identity))
    {
      m_face->put(response);
    }
  else
    {
      Name wrappedName;
      wrappedName.append(invitationRoutingPrefix)
        .append(ROUTING_PREFIX_SEPARATOR, 2)
        .append(response.getName());

      _LOG_DEBUG("onInvitationResponded: prepare reply " << wrappedName);
      
      Data wrappedData(wrappedName);
      wrappedData.setContent(response.wireEncode());
      wrappedData.setFreshnessPeriod(1000);

      m_keyChain.signByIdentity(wrappedData, m_identity);
      m_face->put(wrappedData);
    }

  // create chatroom
  if(accepted)
    {
      Invitation invitation(invitationName);
      Name chatroomPrefix;
      chatroomPrefix.append("ndn")
        .append("broadcast")
        .append("ChronoChat")
        .append(invitation.getChatroom());

      //We should create a chatroom specific key/cert (which should be created in the first half of this method, but let's use the default one for now.
      shared_ptr<IdentityCertificate> idCert = m_keyChain.getCertificate(m_keyChain.getDefaultCertificateNameForIdentity(m_identity));
      ChatDialog* chatDialog = new ChatDialog(&m_contactManager, m_face, *idCert, chatroomPrefix, m_localPrefix, m_nick, true);
      chatDialog->addSyncAnchor(invitation);

      addChatDialog(QString::fromStdString(invitation.getChatroom()), chatDialog);
      chatDialog->show();
    }
}

void
Controller::onShowChatMessage(const QString& chatroomName, const QString& from, const QString& data)
{
  m_trayIcon->showMessage(QString("Chatroom %1 has a new message").arg(chatroomName), 
                          QString("<%1>: %2").arg(from).arg(data), 
                          QSystemTrayIcon::Information, 20000);
  m_trayIcon->setIcon(QIcon(":/images/note.png"));
}

void
Controller::onResetIcon()
{
  m_trayIcon->setIcon(QIcon(":/images/icon_small.png"));
}

void
Controller::onRemoveChatDialog(const QString& chatroomName)
{
  ChatDialogList::iterator it = m_chatDialogList.find(chatroomName.toStdString());

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

      QAction* chatAction = m_chatActionList[chatroomName.toStdString()];
      QAction* closeAction = m_closeActionList[chatroomName.toStdString()];
      if(chatAction)
        delete chatAction;
      if(closeAction)
        delete closeAction;
      
      m_chatActionList.erase(chatroomName.toStdString());
      m_closeActionList.erase(chatroomName.toStdString());
      
      updateMenu();
    }
}

void
Controller::onWarning(const QString& msg)
{
  QMessageBox::information(this, tr("ChronoChat"), msg);
}

void
Controller::onError(const QString& msg) 
{
  QMessageBox::critical(this, tr("ChronoChat"), msg, QMessageBox::Ok);
  exit(1);
}

void
Controller::onInvitationInterest(const Name& prefix, const Interest& interest, size_t routingPrefixOffset)
{
  _LOG_DEBUG("onInvitationInterest: " << interest.getName());
  shared_ptr<Interest> invitationInterest = make_shared<Interest>(boost::cref(interest.getName().getSubName(routingPrefixOffset)));

  // check if the chatroom already exists;
  try
    {
      Invitation invitation(invitationInterest->getName());
      if(m_chatDialogList.find(invitation.getChatroom()) != m_chatDialogList.end())
        return;
    }
  catch(Invitation::Error& e)
    {
      // Cannot parse the invitation;
      return;
    }

  OnInterestValidated onValidated = bind(&Controller::onInvitationValidated, this, _1);
  OnInterestValidationFailed onValidationFailed = bind(&Controller::onInvitationValidationFailed, this, _1, _2);
  m_validator.validate(*invitationInterest, onValidated, onValidationFailed);
}

} // namespace chronos

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