//=========================================================================
//  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_jobsManifest_h
#define __smtk_simulation_ace3p_jobsManifest_h
#include <string>

#include "nlohmann/json.hpp"

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

namespace smtk
{
namespace simulation
{
namespace ace3p
{

// @brief builder for Job Records
// @long this acts as a form to be filled out, and then returns a valid json Job Record with as many fields filled out
//       as the user specified. Any requisite fields not filled out will be given placeholder values
struct JobRecordGenerator
{
  // constructor: fill out a blank Job Record
  JobRecordGenerator()
  {
    m_data = {
      {"slurm_id",        "0"},
      {"cumulus_id",      "0"},
      {"job_name",         ""},
      {"machine",          ""},
      {"analysis",         ""},
      {"analysis_id",      ""},
      {"nodes",           "0"},
      {"processes",       "0"},
      {"runtime",         "0"},
      {"status",           ""},
      {"submission_time",  ""},
      {"notes",            ""},
      {"runtime_job_folder",   ""},
      {"local_job_folder",     ""},
      {"runtime_input_folder", ""}
    };
  }

  // record the slurm ID of the job
  void slurmID(std::string s){m_data["slurm_id"] = s;}

  // record the cumulus ID of the job
  void cumulusID(std::string s){m_data["cumulus_id"] = s;}

  // record the user-specified name of the job
  void jobName(std::string s){m_data["job_name"] = s;}

  // record the machine the job was submitted to
  void machine(std::string  s){m_data["machine"] = s;}

  // record the analyis of the job
  void analysis(std::string s){m_data["analysis"] = s;}

  // record the UUID of the analysis progenitor this job
  void analysisID(std::string s){m_data["analysis_id"] = s;}

  // record the number of nodes requested by the job
  void nodes(int s) {m_data["nodes"] = std::to_string(s);}
  void nodes(std::string s){m_data["nodes"] = s;}

  // record the number of processes requested by the job
  void processes(int s){m_data["processes"] = std::to_string(s);}
  void processes(std::string s){m_data["processes"] = s;}

  // record the runtime (in seconds) of the job
  void runtime(int s){m_data["runtime"] = std::to_string(s);}
  void runtime(std::string s){m_data["runtime"] = s;}

  // record the submission timestamp
  void submissionTime(std::string s) {m_data["submission_time"] = s;}

  // record the user-specified notes of the job
  void notes(std::string s){m_data["notes"] = s;}

  // record the runtime folder the job was submitted from
  void runtimeJobFolder(std::string  s){m_data["runtime_job_folder"] = s;}

  // record the folder on the local filesystem for any job data
  void localJobFolder(std::string s){m_data["local_job_folder"] = s;}

  // record the optional input folder specified with the job
  void runtimeInputFolder(std::string  s){m_data["runtime_input_folder"] = s;}

  // record job status
  void status(std::string s){m_data["status"] = s;}

  // return the contained json Job Record
  nlohmann::json get(){return m_data;}

  // Job Record data stored in json format
  nlohmann::json m_data;
};

// represents a Jobs Manifest for a project
class SMTKACE3P_EXPORT JobsManifest
{
public:

  // constructor
  JobsManifest()
  {
    m_data["Jobs"] = nlohmann::json::array();
  }
  JobsManifest(nlohmann::json data);

  // get a data entry from internal m_data by key.
  // return false if key not found (value will be set to empty string)
  bool getField(const int index, const std::string key, std::string& value) const;

  // append a new Job Record to the manifest
  bool addJobRecord(nlohmann::json job);

  // write data to a job record field
  bool setField(
    const int idx,
    const std::string key,
    const std::string value
  );

  // write the jobs manifest to file
  bool write(std::string filename) const;

  // read a jobs manifest from file
  bool read(std::string filename);

  size_t size() const {return m_data["Jobs"].size();}

  // get the underlying data structure
  nlohmann::json getData() {return m_data;}

protected:
  // set the internal data of the job manifest
  bool setInternalData(nlohmann::json data);

private:
  nlohmann::json m_data;
};

}
}
}
#endif
