/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCTestSubmitCommand.h"

#include <set>
#include <sstream>
#include <utility>

#include <cm/memory>
#include <cm/vector>
#include <cmext/algorithm>
#include <cmext/string_view>

#include "cmCTest.h"
#include "cmCTestSubmitHandler.h"
#include "cmCommand.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

class cmExecutionStatus;

/**
 * This is a virtual constructor for the command.
 */
std::unique_ptr<cmCommand> cmCTestSubmitCommand::Clone()
{
  auto ni = cm::make_unique<cmCTestSubmitCommand>();
  ni->CTest = this->CTest;
  ni->CTestScriptHandler = this->CTestScriptHandler;
  return std::unique_ptr<cmCommand>(std::move(ni));
}

cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
{
  const std::string* submitURL = !this->SubmitURL.empty()
    ? &this->SubmitURL
    : this->Makefile->GetDef("CTEST_SUBMIT_URL");

  if (submitURL) {
    this->CTest->SetCTestConfiguration("SubmitURL", *submitURL, this->Quiet);
  } else {
    this->CTest->SetCTestConfigurationFromCMakeVariable(
      this->Makefile, "DropMethod", "CTEST_DROP_METHOD", this->Quiet);
    this->CTest->SetCTestConfigurationFromCMakeVariable(
      this->Makefile, "DropSiteUser", "CTEST_DROP_SITE_USER", this->Quiet);
    this->CTest->SetCTestConfigurationFromCMakeVariable(
      this->Makefile, "DropSitePassword", "CTEST_DROP_SITE_PASSWORD",
      this->Quiet);
    this->CTest->SetCTestConfigurationFromCMakeVariable(
      this->Makefile, "DropSite", "CTEST_DROP_SITE", this->Quiet);
    this->CTest->SetCTestConfigurationFromCMakeVariable(
      this->Makefile, "DropLocation", "CTEST_DROP_LOCATION", this->Quiet);
  }

  this->CTest->SetCTestConfigurationFromCMakeVariable(
    this->Makefile, "CurlOptions", "CTEST_CURL_OPTIONS", this->Quiet);

  const char* notesFilesVariable =
    this->Makefile->GetDefinition("CTEST_NOTES_FILES");
  if (notesFilesVariable) {
    std::vector<std::string> notesFiles = cmExpandedList(notesFilesVariable);
    this->CTest->GenerateNotesFile(notesFiles);
  }

  const char* extraFilesVariable =
    this->Makefile->GetDefinition("CTEST_EXTRA_SUBMIT_FILES");
  if (extraFilesVariable) {
    std::vector<std::string> extraFiles = cmExpandedList(extraFilesVariable);
    if (!this->CTest->SubmitExtraFiles(extraFiles)) {
      this->SetError("problem submitting extra files.");
      return nullptr;
    }
  }

  cmCTestSubmitHandler* handler = this->CTest->GetSubmitHandler();
  handler->Initialize();

  // If no FILES or PARTS given, *all* PARTS are submitted by default.
  //
  // If FILES are given, but not PARTS, only the FILES are submitted
  // and *no* PARTS are submitted.
  //  (This is why we select the empty "noParts" set in the
  //   FilesMentioned block below...)
  //
  // If PARTS are given, only the selected PARTS are submitted.
  //
  // If both PARTS and FILES are given, only the selected PARTS *and*
  // all the given FILES are submitted.

  // If given explicit FILES to submit, pass them to the handler.
  //
  if (this->FilesMentioned) {
    // Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
    // were also explicitly mentioned, they will be selected below...
    // But FILES with no PARTS mentioned should just submit the FILES
    // without any of the default parts.
    //
    handler->SelectParts(std::set<cmCTest::Part>());
    handler->SelectFiles(
      std::set<std::string>(this->Files.begin(), this->Files.end()));
  }

  // If a PARTS option was given, select only the named parts for submission.
  //
  if (this->PartsMentioned) {
    auto parts =
      cmMakeRange(this->Parts).transform([this](std::string const& arg) {
        return this->CTest->GetPartFromName(arg);
      });
    handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
  }

  // Pass along any HTTPHEADER to the handler if this option was given.
  if (!this->HttpHeaders.empty()) {
    handler->SetHttpHeaders(this->HttpHeaders);
  }

  handler->SetOption("RetryDelay", this->RetryDelay.c_str());
  handler->SetOption("RetryCount", this->RetryCount.c_str());
  handler->SetOption("InternalTest", this->InternalTest ? "ON" : "OFF");

  handler->SetQuiet(this->Quiet);

  if (this->CDashUpload) {
    handler->SetOption("CDashUploadFile", this->CDashUploadFile.c_str());
    handler->SetOption("CDashUploadType", this->CDashUploadType.c_str());
  }
  return handler;
}

bool cmCTestSubmitCommand::InitialPass(std::vector<std::string> const& args,
                                       cmExecutionStatus& status)
{
  this->CDashUpload = !args.empty() && args[0] == "CDASH_UPLOAD";

  bool ret = this->cmCTestHandlerCommand::InitialPass(args, status);

  if (!this->BuildID.empty()) {
    this->Makefile->AddDefinition(this->BuildID, this->CTest->GetBuildID());
  }

  return ret;
}

void cmCTestSubmitCommand::BindArguments()
{
  if (this->CDashUpload) {
    // Arguments specific to the CDASH_UPLOAD signature.
    this->Bind("CDASH_UPLOAD", this->CDashUploadFile);
    this->Bind("CDASH_UPLOAD_TYPE", this->CDashUploadType);
  } else {
    // Arguments that cannot be used with CDASH_UPLOAD.
    this->Bind("PARTS"_s, this->Parts);
    this->Bind("FILES"_s, this->Files);
  }
  // Arguments used by both modes.
  this->Bind("BUILD_ID"_s, this->BuildID);
  this->Bind("HTTPHEADER"_s, this->HttpHeaders);
  this->Bind("RETRY_COUNT"_s, this->RetryCount);
  this->Bind("RETRY_DELAY"_s, this->RetryDelay);
  this->Bind("SUBMIT_URL"_s, this->SubmitURL);
  this->Bind("INTERNAL_TEST_CHECKSUM", this->InternalTest);

  // Look for other arguments.
  this->cmCTestHandlerCommand::BindArguments();
}

void cmCTestSubmitCommand::CheckArguments(
  std::vector<std::string> const& keywords)
{
  this->PartsMentioned =
    !this->Parts.empty() || cm::contains(keywords, "PARTS");
  this->FilesMentioned =
    !this->Files.empty() || cm::contains(keywords, "FILES");

  cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
    cmCTest::Part p = this->CTest->GetPartFromName(arg);
    if (p == cmCTest::PartCount) {
      std::ostringstream e;
      e << "Part name \"" << arg << "\" is invalid.";
      this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return true;
    }
    return false;
  });

  cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
    if (!cmSystemTools::FileExists(arg)) {
      std::ostringstream e;
      e << "File \"" << arg << "\" does not exist. Cannot submit "
        << "a non-existent file.";
      this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
      return true;
    }
    return false;
  });
}
