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

#include <algorithm>
#include <cstdlib>
#include <sstream>

#include <cm/string_view>

#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmWorkingDirectory.h"

namespace {
// class to save and restore the error state for ctest_* commands
// if a ctest_* command has a CAPTURE_CMAKE_ERROR then put the error
// state into there and restore the system wide error to what
// it was before the command ran
class SaveRestoreErrorState
{
public:
  SaveRestoreErrorState()
  {
    this->InitialErrorState = cmSystemTools::GetErrorOccurredFlag();
    cmSystemTools::ResetErrorOccurredFlag(); // rest the error state
    this->CaptureCMakeErrorValue = false;
  }
  // if the function has a CAPTURE_CMAKE_ERROR then we should restore
  // the error state to what it was before the function was run
  // if not then let the error state be what it is
  void CaptureCMakeError() { this->CaptureCMakeErrorValue = true; }
  ~SaveRestoreErrorState()
  {
    // if we are not saving the return value then make sure
    // if it was in error it goes back to being in error
    // otherwise leave it be what it is
    if (!this->CaptureCMakeErrorValue) {
      if (this->InitialErrorState) {
        cmSystemTools::SetErrorOccurred();
      }
      return;
    }
    // if we have saved the error in a return variable
    // then put things back exactly like they were
    bool currentState = cmSystemTools::GetErrorOccurredFlag();
    // if the state changed during this command we need
    // to handle it, if not then nothing needs to be done
    if (currentState != this->InitialErrorState) {
      // restore the initial error state
      if (this->InitialErrorState) {
        cmSystemTools::SetErrorOccurred();
      } else {
        cmSystemTools::ResetErrorOccurredFlag();
      }
    }
  }
  SaveRestoreErrorState(const SaveRestoreErrorState&) = delete;
  SaveRestoreErrorState& operator=(const SaveRestoreErrorState&) = delete;

private:
  bool InitialErrorState;
  bool CaptureCMakeErrorValue;
};
}

bool cmCTestHandlerCommand::InvokeImpl(
  BasicArguments& args, std::vector<std::string> const& unparsed,
  cmExecutionStatus& status, std::function<bool()> handler) const
{
  // save error state and restore it if needed
  SaveRestoreErrorState errorState;
  if (!args.CaptureCMakeError.empty()) {
    errorState.CaptureCMakeError();
  }

  bool success = [&]() -> bool {
    if (args.MaybeReportError(status.GetMakefile())) {
      return true;
    }

    std::sort(args.ParsedKeywords.begin(), args.ParsedKeywords.end());
    auto const it = std::adjacent_find(args.ParsedKeywords.begin(),
                                       args.ParsedKeywords.end());
    if (it != args.ParsedKeywords.end()) {
      status.SetError(cmStrCat("called with more than one value for ", *it));
      return false;
    }

    if (!unparsed.empty()) {
      status.SetError(
        cmStrCat("called with unknown argument \"", unparsed.front(), "\"."));
      return false;
    }

    return handler();
  }();

  if (args.CaptureCMakeError.empty()) {
    return success;
  }

  if (!success) {
    cmCTestLog(this->CTest, ERROR_MESSAGE,
               this->GetName() << ' ' << status.GetError() << '\n');
  }

  cmMakefile& mf = status.GetMakefile();
  success = success && !cmSystemTools::GetErrorOccurredFlag();
  mf.AddDefinition(args.CaptureCMakeError, success ? "0" : "-1");
  return true;
}

bool cmCTestHandlerCommand::ExecuteHandlerCommand(
  HandlerArguments& args, cmExecutionStatus& status) const
{
  cmMakefile& mf = status.GetMakefile();

  // Process input arguments.
  this->CheckArguments(args, status);

  // Set the config type of this ctest to the current value of the
  // CTEST_CONFIGURATION_TYPE script variable if it is defined.
  // The current script value trumps the -C argument on the command
  // line.
  cmValue ctestConfigType = mf.GetDefinition("CTEST_CONFIGURATION_TYPE");
  if (ctestConfigType) {
    this->CTest->SetConfigType(*ctestConfigType);
  }

  if (!args.Build.empty()) {
    this->CTest->SetCTestConfiguration(
      "BuildDirectory", cmSystemTools::CollapseFullPath(args.Build),
      args.Quiet);
  } else {
    std::string const& bdir = mf.GetSafeDefinition("CTEST_BINARY_DIRECTORY");
    if (!bdir.empty()) {
      this->CTest->SetCTestConfiguration(
        "BuildDirectory", cmSystemTools::CollapseFullPath(bdir), args.Quiet);
    } else {
      cmCTestLog(this->CTest, ERROR_MESSAGE,
                 "CTEST_BINARY_DIRECTORY not set" << std::endl);
    }
  }
  if (!args.Source.empty()) {
    cmCTestLog(this->CTest, DEBUG,
               "Set source directory to: " << args.Source << std::endl);
    this->CTest->SetCTestConfiguration(
      "SourceDirectory", cmSystemTools::CollapseFullPath(args.Source),
      args.Quiet);
  } else {
    this->CTest->SetCTestConfiguration(
      "SourceDirectory",
      cmSystemTools::CollapseFullPath(
        mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY")),
      args.Quiet);
  }

  if (cmValue changeId = mf.GetDefinition("CTEST_CHANGE_ID")) {
    this->CTest->SetCTestConfiguration("ChangeId", *changeId, args.Quiet);
  }

  cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl);
  auto handler = this->InitializeHandler(args, status);
  if (!handler) {
    cmCTestLog(this->CTest, ERROR_MESSAGE,
               "Cannot instantiate test handler " << this->GetName()
                                                  << std::endl);
    return false;
  }

  handler->SetAppendXML(args.Append);

  handler->PopulateCustomVectors(&mf);
  if (!args.SubmitIndex.empty()) {
    handler->SetSubmitIndex(atoi(args.SubmitIndex.c_str()));
  }
  cmWorkingDirectory workdir(
    this->CTest->GetCTestConfiguration("BuildDirectory"));
  if (workdir.Failed()) {
    status.SetError(workdir.GetError());
    return false;
  }

  // reread time limit, as the variable may have been modified.
  this->CTest->SetTimeLimit(mf.GetDefinition("CTEST_TIME_LIMIT"));
  handler->SetCMakeInstance(mf.GetCMakeInstance());

  int res = handler->ProcessHandler();
  if (!args.ReturnValue.empty()) {
    mf.AddDefinition(args.ReturnValue, std::to_string(res));
  }
  this->ProcessAdditionalValues(handler.get(), args, status);
  return true;
}

void cmCTestHandlerCommand::CheckArguments(HandlerArguments&,
                                           cmExecutionStatus&) const
{
}

std::unique_ptr<cmCTestGenericHandler>
cmCTestHandlerCommand::InitializeHandler(HandlerArguments&,
                                         cmExecutionStatus&) const
{
  return nullptr;
};

void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*,
                                                    HandlerArguments const&,
                                                    cmExecutionStatus&) const
{
}
