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

#include "cmConditionEvaluator.h"
#include "cmExecutionStatus.h"
#include "cmExpandedCommandArgument.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSystemTools.h"

#include <memory> // IWYU pragma: keep

cmWhileFunctionBlocker::cmWhileFunctionBlocker(cmMakefile* mf)
  : Makefile(mf)
  , Depth(0)
{
  this->Makefile->PushLoopBlock();
}

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

bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
                                               cmMakefile& mf,
                                               cmExecutionStatus& inStatus)
{
  // at end of for each execute recorded commands
  if (lff.Name.Lower == "while") {
    // record the number of while commands past this one
    this->Depth++;
  } else if (lff.Name.Lower == "endwhile") {
    // if this is the endwhile for this while loop then execute
    if (!this->Depth) {
      // Remove the function blocker for this scope or bail.
      std::unique_ptr<cmFunctionBlocker> fb(
        mf.RemoveFunctionBlocker(this, lff));
      if (!fb) {
        return false;
      }

      std::string errorString;

      std::vector<cmExpandedCommandArgument> expandedArguments;
      mf.ExpandArguments(this->Args, expandedArguments);
      MessageType messageType;

      cmListFileContext execContext = this->GetStartingContext();

      cmCommandContext commandContext;
      commandContext.Line = execContext.Line;
      commandContext.Name = execContext.Name;

      cmConditionEvaluator conditionEvaluator(mf, this->GetStartingContext(),
                                              mf.GetBacktrace(commandContext));

      bool isTrue =
        conditionEvaluator.IsTrue(expandedArguments, errorString, messageType);

      while (isTrue) {
        if (!errorString.empty()) {
          std::string err = "had incorrect arguments: ";
          for (cmListFileArgument const& arg : this->Args) {
            err += (arg.Delim ? "\"" : "");
            err += arg.Value;
            err += (arg.Delim ? "\"" : "");
            err += " ";
          }
          err += "(";
          err += errorString;
          err += ").";
          mf.IssueMessage(messageType, err);
          if (messageType == MessageType::FATAL_ERROR) {
            cmSystemTools::SetFatalErrorOccured();
            return true;
          }
        }

        // Invoke all the functions that were collected in the block.
        for (cmListFileFunction const& fn : this->Functions) {
          cmExecutionStatus status;
          mf.ExecuteCommand(fn, status);
          if (status.GetReturnInvoked()) {
            inStatus.SetReturnInvoked();
            return true;
          }
          if (status.GetBreakInvoked()) {
            return true;
          }
          if (status.GetContinueInvoked()) {
            break;
          }
          if (cmSystemTools::GetFatalErrorOccured()) {
            return true;
          }
        }
        expandedArguments.clear();
        mf.ExpandArguments(this->Args, expandedArguments);
        isTrue = conditionEvaluator.IsTrue(expandedArguments, errorString,
                                           messageType);
      }
      return true;
    }
    // decrement for each nested while that ends
    this->Depth--;
  }

  // record the command
  this->Functions.push_back(lff);

  // always return true
  return true;
}

bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
                                          cmMakefile&)
{
  if (lff.Name.Lower == "endwhile") {
    // if the endwhile has arguments, then make sure
    // they match the arguments of the matching while
    if (lff.Arguments.empty() || lff.Arguments == this->Args) {
      return true;
    }
  }
  return false;
}

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

  // create a function blocker
  cmWhileFunctionBlocker* f = new cmWhileFunctionBlocker(this->Makefile);
  f->Args = args;
  this->Makefile->AddFunctionBlocker(f);

  return true;
}
