//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================

#include "smtk/simulation/ace3p/examples/cxx/qtJobTrackerTestWidget.h"

// #include "smtk/cumulus/jobspanel/cumulusproxy.h"
#include "smtk/newt/qtNewtInterface.h"
#include "smtk/simulation/ace3p/qt/qtCumulusJobTracker.h"
#include "smtk/simulation/ace3p/qt/qtNewtJobTracker.h"

#include "smtk/simulation/ace3p/examples/cxx/ui_qtJobTrackerTestWidget.h"

#include <QDebug>
#include <QJsonObject>
#include <QMessageBox>
#include <QNetworkReply>
#include <QString>
#include <QTextStream>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

qtJobTrackerTestWidget::qtJobTrackerTestWidget(QWidget* parentWidget)
  : QWidget(parentWidget)
#ifdef USE_NEWT_TRACKER
  , m_jobTracker(new qtNewtJobTracker(this))
#else
  , m_jobTracker(new qtCumulusJobTracker(this))
#endif
  , ui(new Ui::qtJobTrackerTestWidget)
{
  this->ui->setupUi(this);

#ifdef USE_NEWT_TRACKER
  this->setWindowTitle("NEWT Job Tracker");
  this->ui->m_jobId1Label->setText("SLURM Job Id 1");
  this->ui->m_jobId2Label->setText("SLURM Job Id 2");
#else
  this->ui->m_submitWidget->hide();

  this->setWindowTitle("Cumulus Job Tracker");
  this->ui->m_jobId1Label->setText("Cumulus Job Id 1");
  this->ui->m_jobId2Label->setText("Cumulus Job Id 2");
#endif

  m_jobTracker->setPollingIntervalSeconds(5);

  QObject::connect(
    this->ui->m_loginButton, &QPushButton::clicked, this, &qtJobTrackerTestWidget::onLoginTrigger);
  QObject::connect(
    this->ui->m_loadJobsButton,
    &QPushButton::clicked,
    this,
    &qtJobTrackerTestWidget::onLoadJobsTrigger);
  QObject::connect(
    this->ui->m_pollOnceButton,
    &QPushButton::clicked,
    this,
    &qtJobTrackerTestWidget::onPollOnceTrigger);
  QObject::connect(
    this->ui->m_pollContinuousCheckBox,
    &QCheckBox::toggled,
    this,
    &qtJobTrackerTestWidget::onPollContinuousToggled);
  QObject::connect(
    this->ui->m_submitJobButton,
    &QPushButton::clicked,
    this,
    &qtJobTrackerTestWidget::onSubmitJobTrigger);

  QObject::connect(
    m_jobTracker, &qtAbstractJobTracker::jobStatus, this, &qtJobTrackerTestWidget::onJobStatus);
  QObject::connect(m_jobTracker, &qtAbstractJobTracker::pollingStateChanged, [this](bool polling) {
    QString text = polling ? "ON" : "Off";
    this->ui->m_pollingStateLabel->setText(text);
  });
}

void qtJobTrackerTestWidget::onJobStatus(
  const QString& /*cumulusJobId*/,
  const QString& status,
  const QString& jobId)
{
  QString message;
  QTextStream qs(&message);
  qs << "job status for " << jobId << ", status " << status << ".";
  this->ui->m_listWidget->addItem(message);
}

void qtJobTrackerTestWidget::onNewtLoginComplete(const QString& userName)
{
  QString message;
  QTextStream qs(&message);
  qs << "Logged in as user " << userName << ".";
  this->ui->m_listWidget->addItem(message);

#ifndef USE_NEWT_TRACKER
  // Log into girder/cumulus
  auto cumulus = cumulus::CumulusProxy::instance();
  QObject::connect(cumulus.get(), &cumulus::CumulusProxy::authenticationFinished, [this]() {
    this->ui->m_listWidget->addItem("Girder authentication finished.");
  });
  cumulus->girderUrl("https://ace3p.kitware.com/api/v1");
  QString newtSessionId = this->ui->m_sessionId->text();
  cumulus->authenticateGirder(newtSessionId);
#endif
}

void qtJobTrackerTestWidget::onLoadJobsTrigger()
{
  m_jobTracker->clear();
  int count = 0;

  QString id1 = this->ui->m_jobId1->text();
  if (!id1.isEmpty())
  {
    m_jobTracker->addJob(id1);
    ++count;
  }

  QString id2 = this->ui->m_jobId2->text();
  if (!id2.isEmpty())
  {
    m_jobTracker->addJob(id2);
    ++count;
  }

  QString message;
  QTextStream qs(&message);
  qs << "Number of jobs loaded " << count << ".";
  this->ui->m_listWidget->addItem(message);
}

void qtJobTrackerTestWidget::onLoginTrigger()
{
  // Check input fields
  QString userName = this->ui->m_userName->text();
  if (userName.isEmpty())
  {
    this->ui->m_listWidget->addItem("Cannot login: User name not specified");
    return;
  }

  QString newtSessionId = this->ui->m_sessionId->text();
  if (newtSessionId.isEmpty())
  {
    this->ui->m_listWidget->addItem("Cannot login: NEWT session id not specified");
    return;
  }

  auto* newt = newt::qtNewtInterface::instance();
  QObject::connect(
    newt,
    &newt::qtNewtInterface::loginComplete,
    this,
    &qtJobTrackerTestWidget::onNewtLoginComplete);
  newt->mockLogin(userName, newtSessionId);
}

void qtJobTrackerTestWidget::onPollContinuousToggled(bool checked)
{
  bool started = m_jobTracker->enablePolling(checked);
  qDebug() << "Polling started?" << started;
}

void qtJobTrackerTestWidget::onPollOnceTrigger()
{
  bool started = m_jobTracker->pollOnce();
  qDebug() << "Started poll? " << started;
  if (!started)
  {
    this->ui->m_listWidget->addItem("Did NOT poll server; check console for more info.");
  }
}

void qtJobTrackerTestWidget::onSubmitJobTrigger()
{
  QString filePath = this->ui->m_remoteJobScriptFilePath->text();
  if (filePath.isEmpty())
  {
    this->ui->m_listWidget->addItem("No remote path specified to submit job.");
    return;
  }
#ifdef USE_NEWT_TRACKER
  auto* newt = newt::qtNewtInterface::instance();
  QNetworkReply* reply = newt->requestJobSubmit(filePath, "cori");
  this->ui->m_listWidget->addItem("Job request sent.");

  QObject::connect(reply, &QNetworkReply::finished, [this, newt, reply]() {
    QJsonObject j;
    QString errMessage;
    QString logMessage;
    if (!newt->parseReply(reply, j, errMessage))
    {
      logMessage = QString("Error submitting job: %1").arg(errMessage);
      this->ui->m_listWidget->addItem(logMessage);
      reply->deleteLater();
      return;
    }

    if (j.contains("jobid"))
    {
      QString jobId = j.value("jobid").toString();
      m_jobTracker->addJob(jobId);
      this->ui->m_pollContinuousCheckBox->setChecked(true);
      logMessage = QString("Submitted job id %1").arg(jobId);
    }
    else
    {
      logMessage = "Job was apparently submitted, but job id is missing";
    }
    this->ui->m_listWidget->addItem(logMessage);

    reply->deleteLater();
  });
#else
  this->ui->m_listWidget->addItem("Sorry - job sumbit not supported with this job tracker.");
#endif
}

} // namespace ace3p
} // namespace simulation
} // namespace smtk
