//=========================================================================
//  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.
//=========================================================================
#ifndef smtk_simulation_ace3p_qt_qtCumulusJobTracker_h
#define smtk_simulation_ace3p_qt_qtCumulusJobTracker_h

#include <QObject>

#include "smtk/simulation/ace3p/qt/Exports.h"

#include <QString>

class QNetworkReply;

namespace smtk
{
namespace simulation
{
namespace ace3p
{

/* \brief Manages cumulus I/O for tracking job progress.
 *
 * Accepts jobs to track and makes girder/cumulus requests to get status
 * at periodic intervals. Emits signal for each status update.
 * Stops tracking job when its status is terminal (complete or error).
 * Also supports single-shot update
 *
 */
class SMTKACE3PQTEXT_EXPORT qtCumulusJobTracker : public QObject
{
  Q_OBJECT
  using Superclass = QObject;

public:
  qtCumulusJobTracker(QObject* parent = nullptr);
  ~qtCumulusJobTracker() override;

  // For adding jobs when first loading project, e.g.
  void addJob(const QString& cumulusJobId, bool checkUnique = true);

  // For adding newly-created job
  // * does NOT check is job already in the list
  // * polls cumulus immediately then starts regular interval
  void addNewJob(const QString& cumulusJobId);

  void clear();

  // Return value indicates whether polling is on/off
  bool enablePolling(bool enable);

  // Returns true if polling timer is running
  bool isPolling() const;

  // Gets status for each job.
  bool pollOnce();

  // Set/get polling interval
  void setPollingIntervalSeconds(int intervalSec);
  int pollingIntervalSeconds() const;

signals:
  void error(const QString& msg);
  void jobStatus(
    const QString& cumulusJobId,
    const QString& status,
    const QString& queueJobId,
    qint64 startTimeStamp);
  void pollingStateChanged(bool on);

protected slots:
  void onCumulusError(const QString& msg, QNetworkReply* networkReply);
  void onCumulusReply();
  void onLogin();
  void onTimerEvent();

protected:
  // Make job request to girder/cumulus server
  void requestJob(int index);

  // Checks if timer should be started for next polling interval.
  // The pollNow option will do the first poll immediately.
  bool setNextPoll(bool pollNow = false);

private:
  class Internal;
  Internal* m_internal;
};

} // namespace ace3p
} // namespace simulation
} // namespace smtk
#endif
