//=========================================================================
//  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_common_testing_cxx_randomJobCreator_h
#define smtk_common_testing_cxx_randomJobCreator_h

#include "nlohmann/json.hpp"
#include "smtk/simulation/ace3p/JobsManifest.h"

// stl includes
#include <algorithm>
#include <array>
#include <cctype>
#include <ctime>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <time.h>

namespace
{
std::array<std::string, 50> randomNouns = {
  "coffee",  "comparison",   "history",   "administration", "menu",        "environment",
  "wood",    "football",     "emphasis",  "success",        "connection",  "honey",
  "poet",    "negotiation",  "way",       "criticism",      "drawer",      "winner",
  "income",  "election",     "device",    "signature",      "mood",        "extent",
  "outcome", "road",         "tension",   "judgment",       "birthday",    "marzipan",
  "funeral", "literature",   "presence",  "reality",        "estate",      "chocolate",
  "cabinet", "cell",         "manager",   "clothes",        "examination", "effort",
  "affair",  "satisfaction", "situation", "theory",         "movie",       "depression",
  "data",    "yeti"
};
const std::array<std::string, 50> randomAdjectives = {
  "lopsided",  "capable",    "diligent", "cut",      "royal",      "nonchalant",   "absent",
  "actually",  "near",       "tall",     "married",  "ratty",      "sordid",       "pumped",
  "hallowed",  "measly",     "red",      "small",    "precocious", "young",        "full",
  "careless",  "harmonious", "chemical", "cheerful", "last",       "merciful",     "youthful",
  "tearful",   "seemly",     "cruel",    "thin",     "useless",    "absurd",       "hospitable",
  "sad",       "beautiful",  "violent",  "premium",  "exotic",     "well-groomed", "nice",
  "technical", "green",      "curved",   "hanging",  "excited",    "asleep",       "elfin",
  "sharp"
};

inline int randInt()
{
  return rand() % 50;
}
inline std::string randNoun()
{
  return randomNouns[randInt()];
}
inline std::string randAdj()
{
  return randomAdjectives[randInt()];
}
std::string randName()
{
  std::stringstream maker;
  maker << "the " << randAdj() << " " << randNoun();
  return maker.str();
}

std::string randAnalysis()
{
  std::array<std::string, 3> s = { "omega3p", "tem3p", "t3p" };
  return s[rand() % 3];
}

bool randIsSet = false;
} // namespace

// create a random job
inline nlohmann::json randomJob()
{
  if (!randIsSet)
  {
    srand(time(NULL));
    randIsSet = true;
  }

  auto jrg = ::smtk::simulation::ace3p::JobRecordGenerator();

  int nNodes = rand() % 4096;

  std::stringstream noteMaker;
  noteMaker << randName() << " ran with " << randName();

  std::stringstream folderMaker;
  folderMaker << "/project/" << randNoun() << "/ace3p/210420";

  std::string analysis = randAnalysis();
  std::string resultsFolder = analysis + "_results";
  std::transform(
    resultsFolder.begin(), resultsFolder.end(), resultsFolder.begin(), [](unsigned char c) {
      return std::tolower(c);
    });

  int jobIDInt = (rand() + 15723) % 9999999;

  // fill out Job Record form
  jrg.jobID(std::to_string(jobIDInt));
  jrg.jobName(randName());
  jrg.machine("local-test");
  jrg.analysis(analysis);
  jrg.analysisID("00000000-0000-0000-0000-000000000000");
  jrg.nodes(nNodes);
  jrg.processes(nNodes * 24);
  jrg.elapsedTime(rand() % 525600);
  std::time_t time = std::time(nullptr) - (rand() % (2 * 525600));
  jrg.submissionTime(std::to_string(time));
  jrg.notes(noteMaker.str());
  jrg.runtimeJobFolder(folderMaker.str());
  jrg.runtimeMeshFileName("meshfile.ncdf");
  jrg.resultsSubfolder(resultsFolder);
  folderMaker << "/out";
  jrg.localJobFolder(folderMaker.str());
  jrg.status("complete");

  return jrg.get();
}
#endif
