/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmFunctionCommand.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 {
std::string const ARGC = "ARGC";
std::string const ARGN = "ARGN";
std::string const ARGV = "ARGV";
std::string const CMAKE_CURRENT_FUNCTION = "CMAKE_CURRENT_FUNCTION";
std::string const CMAKE_CURRENT_FUNCTION_LIST_FILE =
  "CMAKE_CURRENT_FUNCTION_LIST_FILE";
std::string const CMAKE_CURRENT_FUNCTION_LIST_DIR =
  "CMAKE_CURRENT_FUNCTION_LIST_DIR";
std::string const CMAKE_CURRENT_FUNCTION_LIST_LINE =
  "CMAKE_CURRENT_FUNCTION_LIST_LINE";

// define the class for function commands
class cmFunctionHelperCommand
{
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;
  long Line;
};

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

  // Expand the argument list to the function.
  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) {
    auto const errorMsg = cmStrCat(
      "Function invoked with incorrect arguments for function named: ",
      this->Args.front());
    inStatus.SetError(errorMsg);
    return false;
  }

  cmMakefile::FunctionPushPop functionScope(&makefile, this->FilePath,
                                            this->Policies);

  // set the value of argc
  makefile.AddDefinition(ARGC, std::to_string(expandedArgs.size()));
  makefile.MarkVariableAsUsed(ARGC);

  // set the values for ARGV0 ARGV1 ...
  for (auto t = 0u; t < expandedArgs.size(); ++t) {
    auto const value = cmStrCat(ARGV, std::to_string(t));
    makefile.AddDefinition(value, expandedArgs[t]);
    makefile.MarkVariableAsUsed(value);
  }

  // define the formal arguments
  for (auto j = 1u; j < this->Args.size(); ++j) {
    makefile.AddDefinition(this->Args[j], expandedArgs[j - 1]);
  }

  // define ARGV and ARGN
  auto const argvDef = cmList::to_string(expandedArgs);
  auto const eit = expandedArgs.begin() + (this->Args.size() - 1);
  auto const argnDef = cmList::to_string(cmMakeRange(eit, expandedArgs.end()));
  makefile.AddDefinition(ARGV, argvDef);
  makefile.MarkVariableAsUsed(ARGV);
  makefile.AddDefinition(ARGN, argnDef);
  makefile.MarkVariableAsUsed(ARGN);

  makefile.AddDefinition(CMAKE_CURRENT_FUNCTION, this->Args.front());
  makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION);
  makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_FILE, this->FilePath);
  makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_FILE);
  makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_DIR,
                         cmSystemTools::GetFilenamePath(this->FilePath));
  makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_DIR);
  makefile.AddDefinition(CMAKE_CURRENT_FUNCTION_LIST_LINE,
                         std::to_string(this->Line));
  makefile.MarkVariableAsUsed(CMAKE_CURRENT_FUNCTION_LIST_LINE);

  // Invoke all the functions that were collected in the block.
  // for each function
  for (cmListFileFunction const& func : this->Functions) {
    cmExecutionStatus status(makefile);
    if (!makefile.ExecuteCommand(func, status) || status.GetNestedError()) {
      // The error message should have already included the call stack
      // so we do not need to report an error here.
      functionScope.Quiet();
      inStatus.SetNestedError();
      return false;
    }
    if (status.GetReturnInvoked()) {
      makefile.RaiseScope(status.GetReturnVariables());
      break;
    }
    if (status.HasExitCode()) {
      inStatus.SetExitCode(status.GetExitCode());
      break;
    }
  }

  // pop scope on the makefile
  return true;
}

class cmFunctionFunctionBlocker : public cmFunctionBlocker
{
public:
  cm::string_view StartCommandName() const override { return "function"_s; }
  cm::string_view EndCommandName() const override { return "endfunction"_s; }

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

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

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

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

bool cmFunctionFunctionBlocker::Replay(
  std::vector<cmListFileFunction> functions, cmExecutionStatus& status)
{
  cmMakefile& mf = status.GetMakefile();
  // create a new command and add it to cmake
  cmFunctionHelperCommand f;
  f.Args = this->Args;
  f.Functions = std::move(functions);
  f.FilePath = this->GetStartingContext().FilePath;
  f.Line = this->GetStartingContext().Line;
  mf.RecordPolicies(f.Policies);
  return mf.GetState()->AddScriptedCommand(
    this->Args.front(),
    BT<cmState::Command>(std::move(f),
                         mf.GetBacktrace().Push(this->GetStartingContext())),
    mf);
}

} // anonymous namespace

bool cmFunctionCommand(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<cmFunctionFunctionBlocker>();
  cm::append(fb->Args, args);
  status.GetMakefile().AddFunctionBlocker(std::move(fb));

  return true;
}
