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

#include <string>
#include <utility>

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

#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmSystemTools.h"

class cmWhileFunctionBlocker : public cmFunctionBlocker
{
public:
  cmWhileFunctionBlocker(cmMakefile* mf, std::vector<cmListFileArgument> args);
  ~cmWhileFunctionBlocker() override;

  cm::string_view StartCommandName() const override { return "while"_s; }
  cm::string_view EndCommandName() const override { return "endwhile"_s; }

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

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

private:
  cmMakefile* Makefile;
  std::vector<cmListFileArgument> Args;
};

cmWhileFunctionBlocker::cmWhileFunctionBlocker(
  cmMakefile* const mf, std::vector<cmListFileArgument> args)
  : Makefile{ mf }
  , Args{ std::move(args) }
{
  this->Makefile->PushLoopBlock();
}

cmWhileFunctionBlocker::~cmWhileFunctionBlocker()
{
  this->Makefile->PopLoopBlock();
}

bool cmWhileFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
                                            cmMakefile&) const
{
  return lff.Arguments().empty() || lff.Arguments() == this->Args;
}

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

  cmListFileBacktrace whileBT =
    mf.GetBacktrace().Push(this->GetStartingContext());

  std::vector<cmExpandedCommandArgument> expandedArguments;
  // At least same size expected for `expandedArguments` as `Args`
  expandedArguments.reserve(this->Args.size());

  auto expandArgs = [&mf](std::vector<cmListFileArgument> const& args,
                          std::vector<cmExpandedCommandArgument>& out)
    -> std::vector<cmExpandedCommandArgument>& {
    out.clear();
    mf.ExpandArguments(args, out);
    return out;
  };

  // For compatibility with projects that do not set CMP0130 to NEW,
  // we tolerate condition errors that evaluate to false.
  bool enforceError = true;
  std::string errorString;
  MessageType messageType;

  for (cmConditionEvaluator conditionEvaluator(mf, whileBT);
       (enforceError = /* enforce condition errors that evaluate to true */
        conditionEvaluator.IsTrue(expandArgs(this->Args, expandedArguments),
                                  errorString, messageType));) {
    // 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()) {
        inStatus.SetReturnInvoked(status.GetReturnVariables());
        return true;
      }
      if (status.GetBreakInvoked()) {
        return true;
      }
      if (status.GetContinueInvoked()) {
        break;
      }
      if (status.HasExitCode()) {
        inStatus.SetExitCode(status.GetExitCode());
        return true;
      }
      if (cmSystemTools::GetFatalErrorOccurred()) {
        return true;
      }
    }
  }

  if (!errorString.empty() && !enforceError) {
    // This error should only be enforced if CMP0130 is NEW.
    if (mf.GetPolicyStatus(cmPolicies::CMP0130) != cmPolicies::OLD) {
      enforceError = true;
    }
  }

  if (!errorString.empty() && enforceError) {
    std::string err = "while() given incorrect arguments:\n ";
    for (auto const& i : expandedArguments) {
      err += " ";
      err += cmOutputConverter::EscapeForCMake(i.GetValue());
    }
    err += "\n";
    err += errorString;
    if (mf.GetPolicyStatus(cmPolicies::CMP0130) == cmPolicies::WARN) {
      mf.IssuePolicyWarning(cmPolicies::CMP0130, {}, err, whileBT);
    } else {
      mf.IssueMessage(messageType, err, whileBT);
      if (messageType == MessageType::FATAL_ERROR) {
        cmSystemTools::SetFatalErrorOccurred();
      }
    }
  }

  return true;
}

bool cmWhileCommand(std::vector<cmListFileArgument> const& args,
                    cmExecutionStatus& status)
{
  if (args.empty()) {
    status.SetError("called with incorrect number of arguments");
    return false;
  }

  // create a function blocker
  auto& makefile = status.GetMakefile();
  makefile.AddFunctionBlocker(
    cm::make_unique<cmWhileFunctionBlocker>(&makefile, args));

  return true;
}
