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

#include "cmBlockCommand.h"

#include <cstdint>
#include <initializer_list>
#include <utility>

#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#include <cmext/enum_set>
#include <cmext/string_view>

#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

namespace {
enum class ScopeType : std::uint8_t
{
  VARIABLES,
  POLICIES
};
using ScopeSet = cm::enum_set<ScopeType>;

class BlockScopePushPop
{
public:
  BlockScopePushPop(cmMakefile* m, const ScopeSet& scopes);
  ~BlockScopePushPop() = default;

  BlockScopePushPop(const BlockScopePushPop&) = delete;
  BlockScopePushPop& operator=(const BlockScopePushPop&) = delete;

private:
  std::unique_ptr<cmMakefile::PolicyPushPop> PolicyScope;
  std::unique_ptr<cmMakefile::VariablePushPop> VariableScope;
};

BlockScopePushPop::BlockScopePushPop(cmMakefile* mf, const ScopeSet& scopes)
{
  if (scopes.contains(ScopeType::POLICIES)) {
    this->PolicyScope = cm::make_unique<cmMakefile::PolicyPushPop>(mf);
  }
  if (scopes.contains(ScopeType::VARIABLES)) {
    this->VariableScope = cm::make_unique<cmMakefile::VariablePushPop>(mf);
  }
}

class cmBlockFunctionBlocker : public cmFunctionBlocker
{
public:
  cmBlockFunctionBlocker(cmMakefile* mf, const ScopeSet& scopes,
                         std::vector<std::string> variableNames);
  ~cmBlockFunctionBlocker() override;

  cm::string_view StartCommandName() const override { return "block"_s; }
  cm::string_view EndCommandName() const override { return "endblock"_s; }

  bool EndCommandSupportsArguments() const override { return false; }

  bool ArgumentsMatch(cmListFileFunction const& lff,
                      cmMakefile& mf) const override;

  bool Replay(std::vector<cmListFileFunction> functions,
              cmExecutionStatus& inStatus) override;

private:
  cmMakefile* Makefile;
  ScopeSet Scopes;
  BlockScopePushPop BlockScope;
  std::vector<std::string> VariableNames;
};

cmBlockFunctionBlocker::cmBlockFunctionBlocker(
  cmMakefile* const mf, const ScopeSet& scopes,
  std::vector<std::string> variableNames)
  : Makefile{ mf }
  , Scopes{ scopes }
  , BlockScope{ mf, scopes }
  , VariableNames{ std::move(variableNames) }
{
}

cmBlockFunctionBlocker::~cmBlockFunctionBlocker()
{
  if (this->Scopes.contains(ScopeType::VARIABLES)) {
    this->Makefile->RaiseScope(this->VariableNames);
  }
}

bool cmBlockFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
                                            cmMakefile&) const
{
  // no arguments expected for endblock()
  // but this method should not be called because EndCommandHasArguments()
  // returns false.
  return lff.Arguments().empty();
}

bool cmBlockFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
                                    cmExecutionStatus& inStatus)
{
  auto& mf = inStatus.GetMakefile();

  // Invoke all the functions that were collected in the block.
  for (cmListFileFunction const& fn : functions) {
    cmExecutionStatus status(mf);
    mf.ExecuteCommand(fn, status);
    if (status.GetReturnInvoked()) {
      mf.RaiseScope(status.GetReturnVariables());
      inStatus.SetReturnInvoked(status.GetReturnVariables());
      return true;
    }
    if (status.GetBreakInvoked()) {
      inStatus.SetBreakInvoked();
      return true;
    }
    if (status.GetContinueInvoked()) {
      inStatus.SetContinueInvoked();
      return true;
    }
    if (cmSystemTools::GetFatalErrorOccurred()) {
      return true;
    }
  }
  return true;
}

} // anonymous namespace

bool cmBlockCommand(std::vector<std::string> const& args,
                    cmExecutionStatus& status)
{
  struct Arguments : public ArgumentParser::ParseResult
  {
    cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> ScopeFor;
    ArgumentParser::MaybeEmpty<std::vector<std::string>> Propagate;
  };
  static auto const parser = cmArgumentParser<Arguments>{}
                               .Bind("SCOPE_FOR"_s, &Arguments::ScopeFor)
                               .Bind("PROPAGATE"_s, &Arguments::Propagate);
  std::vector<std::string> unrecognizedArguments;
  auto parsedArgs = parser.Parse(args, &unrecognizedArguments);

  if (!unrecognizedArguments.empty()) {
    status.SetError(cmStrCat("called with unsupported argument \"",
                             unrecognizedArguments[0], '"'));
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }

  if (parsedArgs.MaybeReportError(status.GetMakefile())) {
    cmSystemTools::SetFatalErrorOccurred();
    return true;
  }

  ScopeSet scopes;

  if (parsedArgs.ScopeFor) {
    for (auto const& scope : *parsedArgs.ScopeFor) {
      if (scope == "VARIABLES"_s) {
        scopes.insert(ScopeType::VARIABLES);
        continue;
      }
      if (scope == "POLICIES"_s) {
        scopes.insert(ScopeType::POLICIES);
        continue;
      }
      status.SetError(cmStrCat("SCOPE_FOR unsupported scope \"", scope, '"'));
      cmSystemTools::SetFatalErrorOccurred();
      return false;
    }
  } else {
    scopes = { ScopeType::VARIABLES, ScopeType::POLICIES };
  }
  if (!scopes.contains(ScopeType::VARIABLES) &&
      !parsedArgs.Propagate.empty()) {
    status.SetError(
      "PROPAGATE cannot be specified without a new scope for VARIABLES");
    cmSystemTools::SetFatalErrorOccurred();
    return false;
  }

  // create a function blocker
  auto fb = cm::make_unique<cmBlockFunctionBlocker>(
    &status.GetMakefile(), scopes, parsedArgs.Propagate);
  status.GetMakefile().AddFunctionBlocker(std::move(fb));

  return true;
}
