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

#include <functional>
#include <utility>

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

#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmFunctionBlocker.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

namespace {

// define the class for macro commands
class cmMacroHelperCommand
{
public:
  /**
   * This is called when the command is first encountered in
   * the CMakeLists.txt file.
   */
  bool operator()(std::vector<cmListFileArgument> const& args,
                  cmExecutionStatus& inStatus) const;

  std::vector<std::string> Args;
  std::vector<cmListFileFunction> Functions;
  cmPolicies::PolicyMap Policies;
  cmDiagnostics::DiagnosticMap Diagnostics;
  std::string FilePath;
};

bool cmMacroHelperCommand::operator()(
  std::vector<cmListFileArgument> const& args,
  cmExecutionStatus& inStatus) const
{
  cmMakefile& makefile = inStatus.GetMakefile();

  // Expand the argument list to the macro.
  std::vector<std::string> expandedArgs;
  makefile.ExpandArguments(args, expandedArgs);

  // make sure the number of arguments passed is at least the number
  // required by the signature
  if (expandedArgs.size() < this->Args.size() - 1) {
    std::string errorMsg =
      cmStrCat("Macro invoked with incorrect arguments for macro named: ",
               this->Args[0]);
    inStatus.SetError(errorMsg);
    return false;
  }

  // set the value of argc
  std::string argcDef = std::to_string(expandedArgs.size());

  auto expIt = expandedArgs.begin() + (this->Args.size() - 1);
  std::string expandedArgn =
    cmList::to_string(cmMakeRange(expIt, expandedArgs.end()));
  std::string expandedArgv = cmList::to_string(expandedArgs);
  {
    cmPolicies::PolicyStatus cmp0219 =
      makefile.CheckCMP0219(this->Args[0], expandedArgs);
    if (cmp0219 == cmPolicies::NEW) {
      // Escape macro argument backslashes so that callees receive the same
      // values the caller had.
      for (std::string& expandedArg : expandedArgs) {
        cmSystemTools::ReplaceString(expandedArg, "\\", "\\\\");
      }
      cmSystemTools::ReplaceString(expandedArgn, "\\", "\\\\");
      cmSystemTools::ReplaceString(expandedArgv, "\\", "\\\\");
    } else if (cmp0219 == cmPolicies::WARN) {
      makefile.IssueCMP0219Warning(this->Args[0], expandedArgs);
    }
  }
  std::vector<std::string> variables;
  variables.reserve(this->Args.size() - 1);
  for (unsigned int j = 1; j < this->Args.size(); ++j) {
    variables.emplace_back(cmStrCat("${", this->Args[j], '}'));
  }
  std::vector<std::string> argVs;
  argVs.reserve(expandedArgs.size());
  for (unsigned int j = 0; j < expandedArgs.size(); ++j) {
    argVs.emplace_back(cmStrCat("${ARGV", j, '}'));
  }

  cmMakefile::MacroPushPop macroScope(&makefile, this->FilePath,
                                      this->Policies, this->Diagnostics);

  // Invoke all the functions that were collected in the block.
  // for each function
  for (cmListFileFunction const& func : this->Functions) {
    // Replace the formal arguments and then invoke the command.
    std::vector<cmListFileArgument> newLFFArgs;
    newLFFArgs.reserve(func.Arguments().size());

    // for each argument of the current function
    for (cmListFileArgument const& k : func.Arguments()) {
      cmListFileArgument arg;
      arg.Value = k.Value;
      if (k.Delim != cmListFileArgument::Bracket) {
        // replace formal arguments
        for (unsigned int j = 0; j < variables.size(); ++j) {
          cmSystemTools::ReplaceString(arg.Value, variables[j],
                                       expandedArgs[j]);
        }
        // replace argc
        cmSystemTools::ReplaceString(arg.Value, "${ARGC}", argcDef);

        cmSystemTools::ReplaceString(arg.Value, "${ARGN}", expandedArgn);
        cmSystemTools::ReplaceString(arg.Value, "${ARGV}", expandedArgv);

        // if the current argument of the current function has ${ARGV in it
        // then try replacing ARGV values
        if (arg.Value.find("${ARGV") != std::string::npos) {
          for (unsigned int t = 0; t < expandedArgs.size(); ++t) {
            cmSystemTools::ReplaceString(arg.Value, argVs[t], expandedArgs[t]);
          }
        }
      }
      arg.Delim = k.Delim;
      arg.Line = k.Line;
      newLFFArgs.push_back(std::move(arg));
    }
    cmListFileFunction newLFF{ func.OriginalName(), func.Line(),
                               func.LineEnd(), std::move(newLFFArgs) };
    cmExecutionStatus status(makefile);
    if (!makefile.ExecuteCommand(newLFF, status) || status.GetNestedError()) {
      // The error message should have already included the call stack
      // so we do not need to report an error here.
      macroScope.Quiet();
      inStatus.SetNestedError();
      return false;
    }
    if (status.GetReturnInvoked()) {
      inStatus.SetReturnInvoked(status.GetReturnVariables());
      return true;
    }
    if (status.GetBreakInvoked()) {
      inStatus.SetBreakInvoked();
      return true;
    }
    if (status.GetContinueInvoked()) {
      inStatus.SetContinueInvoked();
      return true;
    }
    if (status.HasExitCode()) {
      inStatus.SetExitCode(status.GetExitCode());
      return true;
    }
  }
  return true;
}

class cmMacroFunctionBlocker : public cmFunctionBlocker
{
public:
  cm::string_view StartCommandName() const override { return "macro"_s; }
  cm::string_view EndCommandName() const override { return "endmacro"_s; }

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

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

  std::vector<std::string> Args;
};

bool cmMacroFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff,
                                            cmMakefile& mf) const
{
  std::vector<std::string> expandedArguments;
  mf.ExpandArguments(lff.Arguments(), expandedArguments);
  return expandedArguments.empty() || expandedArguments[0] == this->Args[0];
}

bool cmMacroFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
                                    cmExecutionStatus& status)
{
  cmMakefile& mf = status.GetMakefile();
  if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0217) !=
      cmPolicies::NEW) {

    mf.AppendProperty("MACROS", this->Args[0]);
  }
  // create a new command and add it to cmake
  cmMacroHelperCommand f;
  f.Args = this->Args;
  f.Functions = std::move(functions);
  f.FilePath = this->GetStartingContext().FilePath;
  mf.RecordPolicies(f.Policies);
  mf.RecordDiagnostics(f.Diagnostics);
  return mf.GetState()->AddScriptedCommand(
    this->Args[0], cmStateEnums::CommandType::Macro,
    BT<cmState::Command>(std::move(f),
                         mf.GetBacktrace().Push(this->GetStartingContext())),
    mf);
}
}

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

  // create a function blocker
  {
    auto fb = cm::make_unique<cmMacroFunctionBlocker>();
    cm::append(fb->Args, args);
    status.GetMakefile().AddFunctionBlocker(std::move(fb));
  }
  return true;
}
