//=========================================================================
//  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_qtAbstractJobTracker_h
#define smtk_simulation_ace3p_qt_qtAbstractJobTracker_h

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

#include <QObject>
#include <QString>
#include <QTimer>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

/* \brief abstract class for deriving specialized job trackers.
  *
*/
class SMTKACE3PQTEXT_EXPORT qtAbstractJobTracker : public QObject
{
  Q_OBJECT
  using Superclass = QObject;

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

  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.
  virtual bool pollOnce();

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

  // add a job to the tracked jobs list
  void addJob(const QString& jobJobId, bool checkUnique = true);

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

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

protected slots:
  virtual void onTimerEvent();

protected:
  // Make job request to the server
  virtual void requestJob(int index) = 0;

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

  class InternalTimer;
  InternalTimer* m_internalTimer;

  // list of string identifiers for jobs
  QStringList m_jobList;
};

//-----------------------------------------------------------------------------
class qtAbstractJobTracker::InternalTimer
{
public:
  bool m_busy = false; // true during network I/O
  bool m_pollingEnabled = false;
  int m_pollingIndex = -1;

  QTimer* m_timer = nullptr;

  InternalTimer()
    : m_timer(new QTimer())
  {
    m_timer->setSingleShot(true);
    m_timer->setInterval(1000 * DefaultPollingSeconds);
  }

  ~InternalTimer()
  {
    m_timer->stop();
    delete m_timer;
  }

private:
  const int DefaultPollingSeconds = 15;
};
} // namespace ace3p
} // namespace simulation
} // namespace smtk
#endif
