//=========================================================================
//  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.
//=========================================================================

// local includes
#include "JobsManifest.h"

// stl includes
#include <fstream>
#include <iostream>

namespace smtk
{
namespace simulation
{
namespace ace3p
{

JobsManifest::JobsManifest(nlohmann::json data)
{
  setInternalData(data);
}

//-------------------------------------------------------------------------
bool JobsManifest::setInternalData(nlohmann::json data)
{
  // TODO add data checking to make sure data is valid
  if (!data["Jobs"].is_array())
  {
    std::cerr << "Jobs Manifest contains no array Jobs of Job Records" << std::endl;
    return false;
  }

  m_data = data["Jobs"];

  // build cumulus id map
  for (int i = 0; i < data["Jobs"].size(); ++i)
  {
    m_cumulus_map[data["Jobs"][i]["cumulus_id"]] = i;
  }

  return true;
}

//-------------------------------------------------------------------------
bool JobsManifest::addJobRecord(nlohmann::json job)
{
  m_data["Jobs"].insert(m_data["Jobs"].end(), job);
  m_cumulus_map[job["cumulus_id"]] = m_data["Jobs"].size() - 1;
  return true;
}

//-------------------------------------------------------------------------
bool JobsManifest::setField(const int idx, const std::string key, const std::string value)
{
  m_data["Jobs"][idx][key] = value;

  // register a cumulus ID with the index of the job
  if (key == "cumulus_id")
  {
    m_cumulus_map[key] = idx;
  }
  return true;
}

//-------------------------------------------------------------------------
bool JobsManifest::write(std::string filename) const
{
  std::string fileContents = m_data.dump(2);
  std::ofstream file(filename);
  file << fileContents;
  file.close();
  return true;
}

//-------------------------------------------------------------------------
bool JobsManifest::read(std::string filename)
{
  std::ifstream file(filename);
  if (!file.good())
  {
    std::cerr << "Cannot read file \"" << filename << "\".\n";
    file.close();
    return false;
  }

  try
  {
    m_data = nlohmann::json::parse(file);
  }
  catch (...)
  {
    std::cerr << "Cannot parse file \"" << filename << "\".\n";
    file.close();
    return false;
  }

  file.close();

  // build map for cumulus IDs
  for (int i = 0; i < m_data["Jobs"].size(); ++i)
  {
    m_cumulus_map[m_data["Jobs"][i]["cumulus_id"]] = i;
  }

  return true;
}

//-------------------------------------------------------------------------
bool JobsManifest::getField(const int index, const std::string key, std::string& value) const
{
  nlohmann::json jArray = m_data["Jobs"];
  if (index >= jArray.size())
  {
    std::cerr << __FILE__ << ":" << __LINE__ << " invalid index: " << index << std::endl;
    value = "?";
    return false;
  }
  nlohmann::json jRecord = jArray[index];
  auto iter = jRecord.find(key);
  if (iter == jRecord.end())
  {
    std::cerr << __FILE__ << ":" << __LINE__ << " "
              << "index " << index << " missing key: " << key << std::endl;
    value = "?";
    return false;
  }

  value = iter->get<std::string>();
  return true;
}

int JobsManifest::getIndexByCumulusID(std::string cumulus_id) const
{
  const auto iter = m_cumulus_map.find(cumulus_id);
  return iter == m_cumulus_map.end() ? -1 : iter->second;
}
} // namespace ace3p
} // namespace simulation
} // namespace smtk
