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

#include <functional>
#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, 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 expIt = expandedArgs.begin() + (this->Args.size() - 1);
  auto const argnDef =
    cmList::to_string(cmMakeRange(expIt, 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;
}
