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

    class KeyGen (LoginDialog): display key generation progress

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

#include "keygen.h"
#include "ui_keygen.h"

#include "contacts.h"
#include "qtfix.h"

#include <QCloseEvent>

#ifndef _WIN32
#include <unistd.h>
#endif

KeyGen::KeyGen(QWidget * /* parent */)
  : Parent(/*parent, Qt::Window*/)
  , ui(new Ui::KeyGen)
  , m_time2gen(0)
  , m_autoShow(false)
  , m_timer(this)
{
  ui->setupUi(this);
  initLanguage(ui->actionEnglish, ui->actionFrench, ui->actionGerman);
  ui->okButton->setText(qApp->translate("QDialogButtonBox", "OK"));
  ui->menubar->adjustSize();
  ui->menubar->resize(width(), ui->menubar->height());
  qtfix::fixPointSize(ui->textLabel, font().pointSize());
  qtfix::fixPointSize(ui->addrValueLabel, font().pointSize());
  qtfix::fixPointSize(ui->okButton, font().pointSize(), 15);

  QPalette pal = ui->addrValueLabel->palette();
  pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Active, QPalette::Highlight));
  pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Active, QPalette::HighlightedText));
  ui->addrValueLabel->setPalette(pal);
  connect(SimCore::get(), SIGNAL(signalKeygen(const QString &, simnumber)),
          this, SLOT(onSignalKeygen(const QString &, simnumber)));
  connect(&m_timer, SIGNAL(timeout()), this, SLOT(onTimerTimeout()));
  connect(this, SIGNAL(finished(int)), this, SLOT(onFinished(int)));
  setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);

  ui->lineEdit->installEventFilter(this);

  ui->label->setPixmap(QPixmap(":/welcome") /*.scaledToWidth(width() - 80, Qt::SmoothTransformation)*/);
  adjustToBiggerSize();
}

KeyGen::~KeyGen()
{
  ui->lineEdit->removeEventFilter(this);
  delete ui;
}

void KeyGen::showNickEdit()
{
  m_autoShow = true;
  if (ui->addrValueLabel->text().isEmpty()) {
    ui->addrValueLabel_lbl->hide();
    ui->addrValueLabel->hide();
    ui->addrValueLabel_text->hide();
  }
  ui->nickLabel->show();
  ui->lineEdit->show();
  ui->lineEdit->setFocus();
}

void KeyGen::closeEvent(QCloseEvent * event)
{
  onFinished(0);
  on_okButton_clicked();
  SimCore::get()->setLoginDialog(0);
  Parent::closeEvent(event);
}

void KeyGen::changeEvent(QEvent * event)
{
  if (event->type() == QEvent::LanguageChange) {
    QString addr = ui->addrValueLabel->text();
    ui->retranslateUi(this);
    ui->addrValueLabel->setText(addr);
    ui->label->setPixmap(QPixmap(":/welcome"));
    ui->okButton->setText(qApp->translate("QDialogButtonBox", "OK"));
    ui->textLabel->setText(tr("Calculating your RSA key for the first time. Please, wait..."));
  }
  Parent::changeEvent(event);
}

void KeyGen::on_okButton_clicked()
{
  if (ui->nickLabel->isVisible()) {
    QString nick = ui->lineEdit->text().trimmed();

    int simres = sim_contact_set_(0, CONTACT_KEY_NICK, sim_pointer_new(nick.toUtf8().data()));
    QString simerr = nick.isEmpty() ? tr("Please, enter a nickname") : SimCore::getError(simres);
    SimCore::get()->getUserContacts();
    if (simres != SIM_OK) {
      qtfix::execMessageBox(true, tr("Setting your nickname not successful (%1)").arg(simres), simerr);
      return;
    }
    sim_audio_hangup_(0);
  }

  qtfix::hideMinimizedWindow(this);
  SimCore::get()->setLoginDialog(0);

  if (m_autoShow) SimCore::showContacts();
  m_autoShow = false;
}

void KeyGen::on_actionEnglish_triggered()
{
  Parent::on_actionEnglish_triggered(ui->actionEnglish, ui->actionFrench, ui->actionGerman);
}

void KeyGen::on_actionFrench_triggered()
{
  Parent::on_actionFrench_triggered(ui->actionEnglish, ui->actionFrench, ui->actionGerman);
}

void KeyGen::on_actionGerman_triggered()
{
  Parent::on_actionGerman_triggered(ui->actionEnglish, ui->actionFrench, ui->actionGerman);
}

void KeyGen::onFinished(int)
{
  /*if (m_time2gen)*/ _exit(0);
}

void KeyGen::onTimerTimeout()
{
  QString elapsed;
  qint64 seconds = m_elapsedTime.elapsed();
  int maxVal = ui->progressBar->maximum();
  int val = m_time2gen > 0 ? maxVal - int(maxVal * (m_time2gen - seconds) / m_time2gen) : m_val + 1;

  ui->progressBar->setValue(m_val = val);
  seconds /= 1000;

  if (seconds <= 3600) {
    elapsed.sprintf(" %02d:%02d", int(seconds / 60 % 60), int(seconds % 60));
  } else {
    elapsed.sprintf(" %d:%02d:%02d", int(seconds / 3600), int(seconds / 60 % 60), int(seconds % 60));
  }
  ui->elapsedLabel->setText(tr("Elapsed:") + elapsed);
}

void KeyGen::onSignalKeygen(const QString & address, simnumber time2gen)
{
  bool init = address == "init";
  if (!time2gen) {
    m_timer.stop();
    m_time2gen = 0;
    ui->textLabel->hide();
    ui->progressBar->hide();
    ui->elapsedLabel->hide();
    ui->estimatedLabel->hide();
    if (!address.isEmpty()) {
      ui->addrValueLabel->setText(address.toUtf8().data());
      ui->addrValueLabel_lbl->show();
      ui->addrValueLabel->show();
      ui->addrValueLabel_text->show();
    } else {
      ui->addrValueLabel_lbl->hide();
      ui->addrValueLabel->hide();
      ui->addrValueLabel_text->hide();
    }
    qtfix::hideMinimizedWindow(this);
    SimCore::get()->setLoginDialog(0);
    ui->okButton->setEnabled(true);
    setWindowTitle(tr("Public key generated"));
  } else {
    ui->textLabel->setText(tr("Calculating your RSA key for the first time. Please, wait..."));
    if (!m_time2gen || init) {
      if (init) ui->textLabel->setText(tr("Checking the speed of your computer. Please, wait..."));
      m_elapsedTime.start();
      setWindowTitle(tr("Generating public key"));
      ui->okButton->setEnabled(false);
      ui->nickLabel->hide();
      ui->lineEdit->hide();
      ui->addrValueLabel->setText("");
      ui->addrValueLabel->hide();
      ui->addrValueLabel_lbl->hide();
      ui->addrValueLabel_text->hide();
      ui->textLabel->show();
      ui->progressBar->show();
      ui->elapsedLabel->show();
      ui->estimatedLabel->show();
      ui->estimatedLabel->setText("");
      ui->elapsedLabel->setText("");
      ui->progressBar->setMaximum(100);
      ui->progressBar->setValue(0);
      restorePosition();
      qtfix::showActivateWindow(this, true);
      SimCore::get()->setLoginDialog(this);
      m_timer.start(1000);
      m_time2gen = -1;
      m_val = 0;
    }

    if (!init) {
      if (m_time2gen <= 0) m_time2gen = m_elapsedTime.elapsed(); // add elapsed time to estimated max
      m_time2gen += time2gen * 1000;
      if (m_time2gen <= 0) m_time2gen = 1;

      int seconds = int(m_time2gen / 1000);
      QString estimated;
      if (seconds < 3600) {
        estimated.sprintf(" %02d:%02d", seconds / 60 % 60, seconds % 60);
      } else {
        estimated.sprintf(" %d:%02d:%02d", seconds / 3600, seconds / 60 % 60, seconds % 60);
      }
      ui->estimatedLabel->setText(tr("Estimated:") + estimated);
    }
  }
  log_info_("ui", "keygen number %lld, elapsed %lld, estimated %lld, value = %d\n",
            time2gen, m_elapsedTime.elapsed() / 1000, m_time2gen / 1000, m_val);
}
