/* 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 <utility>

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

#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 "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;
  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;
  }

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

  // 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);
  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, '}'));
  }
  // 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.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();
  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);
  return mf.GetState()->AddScriptedCommand(
    this->Args[0],
    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;
}
