/**
 * \file core/slurm_process/slurmprocess.h
 * \date 21/09/2023
 * \author Olivier Langella
 * \brief handles execution of processes through slurm
 * workload manager
 */

/*******************************************************************************
 * Copyright (c) 2023 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.fr>.
 *
 * This file is part of i2MassChroQ.
 *
 *     i2MassChroQ is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     i2MassChroQ is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with i2MassChroQ.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

#pragma once
#include "../../utils/workmonitor.h"
#include "../../gui/mainwindow.h"
#include <QTemporaryDir>
#include <QProcess>
#include <QJsonDocument>


/** \def SlurmJobState JOB STATE CODES
 *
 * SlurmJobState as given by the squeue slurm command
 * see documentation below :
 * https://slurm.schedmd.com/squeue.html#lbAG
 */
enum class SlurmJobState : std::int8_t
{
  undefined  = 0, ///< undefined
  COMPLETED  = 1, ///< The job has completed successfully
  COMPLETING = 2, ///< The job is finishing but some processes are still active
  FAILED =
    3, ///< The job terminated with a non-zero exit code and failed to execute
  PENDING =
    4, ///< The job is waiting for resource allocation. It will eventually run
  PREEMPTED =
    5,         ///< The job was terminated because of preemption by another job
  RUNNING = 6, ///< The job currently is allocated to a node and is running
  SUSPENDED =
    7, ///< A running job has been stopped with its cores released to other jobs
  STOPPED    = 8,  ///< A running job has been stopped with its cores retained
  CANCELLED  = 9,  ///< Job cancelled by the user
  not_listed = 10, ///< the job id is not listed in the slurm squeue
  unknown    = 11,
};


/**
 * @todo write docs
 */
class SlurmProcess : public QProcess
{
  Q_OBJECT
  public:
  /**
   * Default constructor
   */
  SlurmProcess();

  /**
   * Destructor
   */
  ~SlurmProcess();

  std::size_t startSlurmBatch(const QFileInfo &batch_file_name);

  bool isRunning();

  bool killJob();

  SlurmJobState getSlurmJobState() const;

  QString getSlurmJobPendingReason() const;

  QString whatAboutMyJob() const;

  void srun(const QDir &current_dir, const QStringList &arguments);

  QJsonDocument getJsonSlurmJobStatusDocument();

  void refreshJsonJobStatus(const QJsonDocument &json_slurm_squeue);

  std::size_t getAverageMemorySizeMegaBytes();

  protected:
  QJsonDocument getJsonDocument(const QString &slurm_command);


  protected:
  private:
  void setSlurmJobState(const QJsonValue &jobid);

  private:
  QString m_runName;
  QString m_slurmSbatchCommand;
  QString m_slurmSrunCommand;
  QString m_slurmScancelCommand;
  QString m_slurmSinfoCommand;
  QString m_slurmSqueueCommand;
  QString m_slurmStatCommand;

  int m_maxLaunchTime = (60000 * 60 * 24); // 1 day

  std::size_t m_slurmJobId = 0;

  SlurmJobState m_slurmJobState = SlurmJobState::undefined;
  QJsonObject m_jsonObjectJob;
};
