//=========================================================================
//  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_qtJobsModel_h
#define smtk_simulation_ace3p_qt_qtJobsModel_h

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

// Qt includes
#include <QAbstractTableModel>
#include <QtGlobal>

// smtk includes
#include "smtk/simulation/ace3p/Project.h"

#include <array>
#include <string>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

class qtCumulusJobTracker;
class qtNewtJobTracker;

class SMTKACE3PQTEXT_EXPORT qtJobsModel : public QAbstractTableModel
{
  Q_OBJECT
  using Superclass = QAbstractTableModel;

public:
  qtJobsModel(QObject* parent);
  virtual ~qtJobsModel() = default;

  enum JobsFields
  {
    JobName = 0,
    AnalysisType,
    Status,
    StartTime,
    Notes,
    JobID,
    Processes,
    Nodes,
    Machine,
    RemoteDir,
    LocalDir,
    InputDir,
    StageID, // this comes from Attribute Resource UUID
    ACDTool_Task
  };

  int rowCount(const QModelIndex& parent = QModelIndex()) const override;
  int columnCount(const QModelIndex& parent = QModelIndex()) const override;
  QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
  QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole)
    const override;
  bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
  Qt::ItemFlags flags(const QModelIndex& index) const override;

  /** \brief Overrides base class to set which column is used for Proxy Model filtering. */
  int filterKeyColumn() const { return static_cast<int>(JobsFields::StageID); }

  qtNewtJobTracker* jobTracker() { return m_jobTracker; }

  void addTestJob(); // TODO - delete later, temporary code for creating a testing project

public slots:
  void onJobAdded(const QString& jobId);
  /** \brief Removes job from project because it's data was overwritten */
  void onJobOverwritten(const QString& jobId);
  void populateJobs(const smtk::project::ProjectPtr project);
  // void updateJobs();
  void clearJobs();
  void onJobStatus(
    const QString& /*cumulusJobId*/,
    const QString& status,
    const QString& queueJobId,
    qint64 startTimeStamp);

  // Requests update for all jobs with non-terminal status
  void enablePolling(bool enable);
  void updateStatus();

signals:
  void pollingStateChanged(bool polling);

protected slots:

protected:
  void initTrackerJobList();

private:
  // job record field names by column
  std::string col2field(JobsFields col) const;

  // column titles
  const QStringList m_headers = {
    "Name", "Analysis", "Status", "Submitted (UTC)", "", "", "", "", "", "", "", "", "", ""
  };

  // number of columns in the table
  const int m_nCols = 14;

  // @brief pointer to the current project
  std::shared_ptr<smtk::simulation::ace3p::Project> m_project = nullptr;

  // @brief pointer to job tracker instance
  qtNewtJobTracker* m_jobTracker = nullptr;
};
} // namespace ace3p
} // namespace simulation
} // namespace smtk
#endif
