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

#include "discovery-panel.hpp"
#include "ui_discovery-panel.h"

#include <QItemSelectionModel>
#include <QModelIndex>
#include <QMessageBox>

#ifndef Q_MOC_RUN
#endif


namespace chronochat {

static const ndn::Name::Component ROUTING_HINT_SEPARATOR =
  ndn::name::Component::fromEscapedString("%F0%2E");

DiscoveryPanel::DiscoveryPanel(QWidget *parent)
  : QDialog(parent)
  , ui(new Ui::DiscoveryPanel)
  , m_chatroomListModel(new QStringListModel)
  , m_rosterListModel(new QStringListModel)
{
  ui->setupUi(this);
  ui->ChatroomList->setModel(m_chatroomListModel);
  ui->RosterList->setModel(m_rosterListModel);

  connect(ui->ChatroomList->selectionModel(),
          SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
          this,
          SLOT(onSelectedChatroomChanged(const QItemSelection &, const QItemSelection &)));
  connect(ui->RosterList->selectionModel(),
          SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
          this,
          SLOT(onSelectedParticipantChanged(const QItemSelection &, const QItemSelection &)));
  connect(ui->join, SIGNAL(clicked()),
          this, SLOT(onJoinClicked()));
  connect(ui->requestInvitation, SIGNAL(clicked()),
          this, SLOT(onRequestInvitation()));

  ui->join->setEnabled(false);
  ui->requestInvitation->setEnabled(false);
  ui->InChatroomWarning->clear();
  m_isParticipant = false;
}

DiscoveryPanel::~DiscoveryPanel()
{
  if (m_chatroomListModel)
    delete m_chatroomListModel;
  if (m_rosterListModel)
    delete m_rosterListModel;
  delete ui;
}

//private methods
void
DiscoveryPanel::resetPanel()
{
  // Clean up General tag.
  ui->NameData->clear();
  ui->NameSpaceData->clear();
  ui->TrustModelData->clear();

  // Clean up Roster tag.
  m_rosterList.clear();
  m_participant.clear();
  m_rosterListModel->setStringList(m_rosterList);

  // Clean up chatroom list.
  m_chatroomList.clear();
  m_chatroom.clear();
  m_chatroomListModel->setStringList(m_chatroomList);

  ui->join->setEnabled(false);
  ui->requestInvitation->setEnabled(false);
  ui->InChatroomWarning->clear();
}

// public slots
void
DiscoveryPanel::onIdentityUpdated(const QString& identity)
{
}

void
DiscoveryPanel::onChatroomListReady(const QStringList& list)
{
  m_chatroomList = list;
  m_chatroomListModel->setStringList(m_chatroomList);
}

void
DiscoveryPanel::onChatroomInfoReady(const ChatroomInfo& info, bool isParticipant)
{
  ui->NameData->setText(QString::fromStdString(info.getName().toUri()));
  ui->NameSpaceData->setText(QString::fromStdString(info.getSyncPrefix().toUri()));

  switch (info.getTrustModel()) {
  case 2:
    {
      ui->TrustModelData->setText(QString("Hierarchical"));
      ui->join->setEnabled(false);
      ui->requestInvitation->setEnabled(false);
      break;
    }
  case 1:
    {
      ui->TrustModelData->setText(QString("Web Of Trust"));
      ui->join->setEnabled(false);
      ui->requestInvitation->setEnabled(false);
      break;
    }
  case 0:
    {
      ui->TrustModelData->setText(QString("None"));
      ui->join->setEnabled(true);
      ui->requestInvitation->setEnabled(false);
      break;
    }
  default:
    {
      ui->TrustModelData->setText(QString("Unrecognized"));
      ui->join->setEnabled(false);
      ui->requestInvitation->setEnabled(false);
    }
  }
  ui->InChatroomWarning->clear();
  m_isParticipant = isParticipant;
  if (m_isParticipant) {
    ui->join->setEnabled(false);
    ui->requestInvitation->setEnabled(false);
    ui->InChatroomWarning->setText(QString("You are already in this chatroom"));
  }

  std::list<Name>roster = info.getParticipants();
  m_rosterList.clear();
  Name::Component routingHint = Name::Component(ROUTING_HINT_SEPARATOR);
  for (const auto& participant : roster) {
    size_t i;
    for (i = 0; i < participant.size(); ++i) {
      if (routingHint == participant.at(i))
        break;
    }
    if (i == participant.size())
      m_rosterList << QString::fromStdString(participant.toUri());
    else
      m_rosterList << QString::fromStdString(participant.getSubName(i + 1).toUri());
  }
  m_rosterListModel->setStringList(m_rosterList);
  ui->RosterList->setModel(m_rosterListModel);
}

// private slots
void
DiscoveryPanel::onSelectedChatroomChanged(const QItemSelection& selected,
                                          const QItemSelection& deselected)
{
  QModelIndexList items = selected.indexes();
  QString chatroomName = m_chatroomListModel->data(items.first(), Qt::DisplayRole).toString();

  bool chatroomFound = false;
  for (int i = 0; i < m_chatroomList.size(); i++) {
    if (chatroomName == m_chatroomList[i]) {
      chatroomFound = true;
      m_chatroom = m_chatroomList[i];
      m_participant.clear();
      break;
    }
  }

  if (!chatroomFound) {
    emit warning("This should not happen: DiscoveryPanel::onSelectedChatroomChanged");
    return;
  }

  emit waitForChatroomInfo(m_chatroom);
}

void
DiscoveryPanel::onSelectedParticipantChanged(const QItemSelection& selected,
                                             const QItemSelection& deselected)
{
  if (m_isParticipant)
    return;

  QModelIndexList items = selected.indexes();
  QString participant = m_rosterListModel->data(items.first(), Qt::DisplayRole).toString();

  bool participantFound = false;
  for (int i = 0; i < m_rosterList.size(); i++) {
    if (participant == m_rosterList[i]) {
      participantFound = true;
      m_participant = m_rosterList[i];
      break;
    }
  }
  ui->requestInvitation->setEnabled(true);
  BOOST_ASSERT(participantFound);
}

void
DiscoveryPanel::onJoinClicked()
{
  emit startChatroom(m_chatroom, false);
}

void
DiscoveryPanel::onRequestInvitation()
{
  emit sendInvitationRequest(m_chatroom, m_participant);
}

void
DiscoveryPanel::onInvitationRequestResult(const std::string& message)
{
  QMessageBox::information(this, tr("Chatroom Discovery"),
                           tr(message.c_str()));
}

} // namespace chronochat

#if WAF
#include "discovery-panel.moc"
#endif
