/** Copyright (c) 2020-2021 The Creators of Simphone

    class ChatWindow (QMainWindow): display a chat frame in a separate window (split-mode)

    See the file COPYING.LESSER.txt for copying permission.
**/

#include "chatwindow.h"
#include "ui_chatwindow.h"

#include "chatframe.h"
#include "contacts.h"

#include <QCloseEvent>

ChatWindow::ChatWindow(QWidget * parent)
  : QMainWindow(parent)
  , ui(new Ui::ChatWindow)
  , m_frame(0)
  , m_saved(false)
  , m_doQuit(false)
  , m_icon(-1)
  , m_title(1)
{
  setAttribute(Qt::WA_DeleteOnClose);
  ui->setupUi(this);
  connect(SimCore::get(), SIGNAL(signalContactStatusChanged(unsigned, int, int)),
          this, SLOT(onSignalContactStatusChanged(unsigned, int, int)));
  connect(SimCore::get(), SIGNAL(signalContactChanged(uint)), this, SLOT(onSignalContactChanged(uint)));
}

ChatWindow::~ChatWindow()
{
  delete ui;
}

void ChatWindow::closeEvent(QCloseEvent * event)
{
  log_xtra_("ui", "%s (q = %d) '%s'\n", __FUNCTION__, m_doQuit,
            m_frame ? m_frame->getContact()->m_nick.toUtf8().data() : 0);
  saveSettings(sim_nil());

  hide();

  if (m_doQuit) {
    m_frame = 0; // just in case
  } else {
    event->ignore();
    if (m_frame) m_frame->getContact()->clearNotifications(Contact::flag_Notifications);
  }

  Contacts::get()->recalcDockMenu();
}

void ChatWindow::changeEvent(QEvent * event)
{
  if (event->type() == QEvent::ActivationChange || event->type() == QEvent::WindowStateChange) {
    if (m_frame && isActiveWindow() && !isMinimized()) {
      m_frame->setFocus();
      ChatFrames::get()->notifyChatUsed(m_frame->getContact()->m_id);
    }
  } else if (event->type() == QEvent::LanguageChange) {
    recalcTitle();
  }
  Parent::changeEvent(event);
}

void ChatWindow::recalcTitle()
{
  QString title;

  log_xtra_("ui", "%s '%s'\n", __FUNCTION__, m_frame->getContact()->m_nick.toUtf8().data());
  if (m_frame->getContact()->isTest()) {
    title = tr("Simphone console");
    if (SimCore::mc_startupUser.isNull()) {
      title.append(" - ");
    } else if (!SimCore::mc_startupUser.isEmpty()) {
      title.append(" - ").append(SimCore::mc_startupUser);
    }
    setWindowIcon(QIcon(":/consoleIcon"));
  } else {
    title = m_frame->getContact()->m_nick;
#ifdef _DEBUG
    title.insert(0, ">");
#endif
    if (m_frame->getContact()->isTyping()) {
      title.append(tr(" (typing...)"));
    } else if (m_title) {
      QString qs;
      m_frame->getContact()->convertStatusToState(m_frame->getContact()->m_status, &qs);
      title.append(" (").append(qs).append(")");
    }
    if ((m_icon > 0 || !Contacts::get()->isAvatarMode()) && m_icon) {
      setWindowIcon(Contacts::get()->getStatusIcon(m_frame->getContact()));
    } else {
      setWindowIcon(QIcon(":/avatar"));
    }
  }
  setWindowTitle(title);
  Contacts::get()->recalcDockMenu(this);
}

void ChatWindow::saveSettings(simtype params)
{
  if (!m_saved && m_frame) {
    //log_note_("ui", "%s\n", __FUNCTION__);
    bool save = true;

    if (sim_get_pointer(params)) {
      m_saved = true; // not 0 only from quit save, so say we are saved
      save = false;
    } else {
      params = sim_table_new(12);
    }

    Contact * c = m_frame->getContact();

    if (!c->isForgotten() && (!c->isDeleted() || c->isTest() || c->isSystem() || c->isMe())) {
      QByteArray savedGeometry = saveGeometry();
      QString ui_key = QString("ui.").append(m_frame->getContact()->getTextId()).append(".geometry");

      simtype s = sim_string_copy_length(savedGeometry.data(), savedGeometry.size());
      sim_table_add_key(params, sim_string_copy(ui_key.toUtf8().data()), s);
      m_frame->getSettings(params);
    }

    if (save) {
      SimParam::set(params);
      sim_table_free(params);
    }
  }
}

void ChatWindow::readSettings()
{
  m_icon = SimParam::get("ui.chat.icon");
  m_title = SimParam::get("ui.chat.title");
  if (m_frame) {
    QString ui_geometry_key = "ui.";
    ui_geometry_key.append(m_frame->getContact()->getTextId()).append(".geometry");

    //log_note_("ui", "%s\n", __FUNCTION__);
    SimParam readGeometry(ui_geometry_key.toUtf8().data());
    if (readGeometry.getLength()) {
      QByteArray qGeometry(readGeometry.getPointer(), readGeometry.getLength());
      restoreGeometry(qGeometry);
    }
  }
}

void ChatWindow::detachFrame()
{
  if (m_frame && centralWidget() && centralWidget()->layout()->count()) {
    log_xtra_("ui", "%s '%s'\n", __FUNCTION__, m_frame->getContact()->m_nick.toUtf8().data());
    centralWidget()->layout()->removeWidget(m_frame);
    m_frame->setParent(0);
    ChatFrames::get()->notifyChatStopped(m_frame->getContact()->m_id);
    disconnect(m_frame, SIGNAL(signalContactQuit()), this, SLOT(close()));
    hide();
  }
}

void ChatWindow::attachFrame(class ChatFrame * frame)
{
  log_xtra_("ui", "%s '%s'\n", __FUNCTION__, frame->getContact()->m_nick.toUtf8().data());
  if (centralWidget()->layout()->indexOf(frame) >= 0) {
    Contacts::get()->recalcDockMenu(this);
    frame->show();
  } else {
    if (m_frame) {
      m_frame->setParent(0);
      centralWidget()->layout()->removeWidget(m_frame);
    }

    frame->setParent(0);
    centralWidget()->layout()->addWidget(frame);
    frame->show();
    bool restore = frame != m_frame;
    m_frame = frame;
    if (restore) readSettings();
    recalcTitle();
    connect(m_frame, SIGNAL(signalContactQuit()), this, SLOT(close()));
  }
}

void ChatWindow::blinkWindow()
{
  log_xtra_("ui", "%s '%s'\n", __FUNCTION__, m_frame ? m_frame->getContact()->m_nick.toUtf8().data() : 0);
  QApplication::alert(this);
}

void ChatWindow::onSignalContactChanged(unsigned id)
{
  if (m_frame && m_frame->getContact()->m_id == int(id)) recalcTitle();
}

void ChatWindow::onSignalContactStatusChanged(unsigned id, int, int)
{
  if (m_frame && m_frame->getContact()->m_id == int(id)) recalcTitle();
}
