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

#include <map>
#include <set>
#include <utility>

#include <cm/string_view>

#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmDiagnostics.h"
#include "cmExecutionStatus.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmRange.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"

namespace {

std::string EscapeArg(std::string const& arg)
{
  // replace ";" with "\;" so output argument lists will split correctly
  std::string escapedArg;
  for (char i : arg) {
    if (i == ';') {
      escapedArg += '\\';
    }
    escapedArg += i;
  }
  return escapedArg;
}

std::string JoinList(std::vector<std::string> const& arg, bool escape)
{
  return escape ? cmList::to_string(cmMakeRange(arg).transform(EscapeArg))
                : cmList::to_string(cmMakeRange(arg));
}

using options_map = std::map<std::string, bool>;
using single_map = std::map<std::string, std::string>;
using multi_map =
  std::map<std::string, ArgumentParser::NonEmpty<std::vector<std::string>>>;
using options_set = std::set<cm::string_view>;

struct UserArgumentParser : public cmArgumentParser<void>
{
  void BindKeywordsMissingValue(std::vector<cm::string_view>& ref)
  {
    this->cmArgumentParser<void>::BindKeywordMissingValue(
      [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); });
  }

  template <typename T, typename H>
  void Bind(std::vector<std::string> const& names,
            std::map<std::string, T>& ref, H duplicateKey)
  {
    for (std::string const& key : names) {
      auto const it = ref.emplace(key, T{}).first;
      bool const inserted = this->cmArgumentParser<void>::Bind(
        cm::string_view(it->first), it->second);
      if (!inserted) {
        duplicateKey(key);
      }
    }
  }
};

} // namespace

static void PassParsedArguments(
  std::string const& prefix, cmMakefile& makefile, options_map const& options,
  single_map const& singleValArgs, multi_map const& multiValArgs,
  std::vector<std::string> const& unparsed, options_set const& keywordsSeen,
  options_set const& keywordsMissingValues, bool parseFromArgV)
{
  for (auto const& iter : options) {
    makefile.AddDefinition(cmStrCat(prefix, iter.first),
                           iter.second ? "TRUE" : "FALSE");
  }

  cmPolicies::PolicyStatus const cmp0174 =
    makefile.GetPolicyStatus(cmPolicies::CMP0174);
  for (auto const& iter : singleValArgs) {
    if (keywordsSeen.find(iter.first) == keywordsSeen.end()) {
      makefile.RemoveDefinition(cmStrCat(prefix, iter.first));
    } else if ((parseFromArgV && cmp0174 == cmPolicies::NEW) ||
               !iter.second.empty()) {
      makefile.AddDefinition(cmStrCat(prefix, iter.first), iter.second);
    } else {
      // The OLD policy behavior doesn't define a variable for an empty or
      // missing value, and we can't differentiate between those two cases.
      if (parseFromArgV && (cmp0174 == cmPolicies::WARN)) {
        makefile.IssueDiagnostic(
          cmDiagnostics::CMD_AUTHOR,
          cmStrCat("The ", iter.first,
                   " keyword was followed by an empty string or no value at "
                   "all. Policy CMP0174 is not set, so "
                   "cmake_parse_arguments() will unset the ",
                   prefix, iter.first,
                   " variable rather than setting it to an empty string."));
      }
      makefile.RemoveDefinition(cmStrCat(prefix, iter.first));
    }
  }

  for (auto const& iter : multiValArgs) {
    if (!iter.second.empty()) {
      makefile.AddDefinition(cmStrCat(prefix, iter.first),
                             JoinList(iter.second, parseFromArgV));
    } else {
      makefile.RemoveDefinition(cmStrCat(prefix, iter.first));
    }
  }

  if (!unparsed.empty()) {
    makefile.AddDefinition(cmStrCat(prefix, "UNPARSED_ARGUMENTS"),
                           JoinList(unparsed, parseFromArgV));
  } else {
    makefile.RemoveDefinition(cmStrCat(prefix, "UNPARSED_ARGUMENTS"));
  }

  if (!keywordsMissingValues.empty()) {
    makefile.AddDefinition(
      cmStrCat(prefix, "KEYWORDS_MISSING_VALUES"),
      cmList::to_string(cmMakeRange(keywordsMissingValues)));
  } else {
    makefile.RemoveDefinition(cmStrCat(prefix, "KEYWORDS_MISSING_VALUES"));
  }
}

bool cmParseArgumentsCommand(std::vector<std::string> const& args,
                             cmExecutionStatus& status)
{
  // cmake_parse_arguments(prefix options single multi <ARGN>)
  //                         1       2      3      4
  // or
  // cmake_parse_arguments(PARSE_ARGV N prefix options single multi)
  // or
  // cmake_parse_arguments(PARSE_ARGN prefix options single multi)
  if (args.size() < 4) {
    status.SetError("must be called with at least 4 arguments.");
    return false;
  }

  auto argIter = args.begin();
  auto argEnd = args.end();
  bool parseFromArg = false;
  unsigned long argStart = 0;
  unsigned long argnc = 0;
  if (*argIter == "PARSE_ARGV") {
    if (args.size() != 6) {
      status.GetMakefile().IssueMessage(
        MessageType::FATAL_ERROR,
        "PARSE_ARGV must be called with exactly 6 arguments.");
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
    parseFromArg = true;
    argIter++; // move past PARSE_ARGV
    if (!cmStrToULong(*argIter, &argStart)) {
      status.GetMakefile().IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("PARSE_ARGV index '", *argIter,
                 "' is not an unsigned integer"));
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
    argIter++; // move past N
  } else if (*argIter == "PARSE_ARGN") {
    if (args.size() != 5) {
      status.GetMakefile().IssueMessage(
        MessageType::FATAL_ERROR,
        "PARSE_ARGN must be called with exactly 5 arguments.");
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
    parseFromArg = true;
    argIter++; // move past PARSE_ARGN
    std::string argncStr = status.GetMakefile().GetSafeDefinition("ARGNC");
    if (!cmStrToULong(argncStr, &argnc)) {
      status.GetMakefile().IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("PARSE_ARGN called with ARGNC='", argncStr,
                 "' that is not an unsigned integer"));
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }
  }
  // the first argument is the prefix
  std::string const prefix = (*argIter++) + "_";

  UserArgumentParser parser;

  // define the result maps holding key/value pairs for
  // options, single values and multi values
  options_map options;
  single_map singleValArgs;
  multi_map multiValArgs;

  // anything else is put into a vector of unparsed strings
  std::vector<std::string> unparsed;

  auto const duplicateKey = [&status](std::string const& key) {
    status.GetMakefile().IssueMessage(
      MessageType::WARNING, cmStrCat("keyword defined more than once: ", key));
  };

  // the second argument is a (cmake) list of options without argument
  cmList list{ *argIter++ };
  parser.Bind(list, options, duplicateKey);

  // the third argument is a (cmake) list of single argument options
  list.assign(*argIter++);
  parser.Bind(list, singleValArgs, duplicateKey);

  // the fourth argument is a (cmake) list of multi argument options
  list.assign(*argIter++);
  parser.Bind(list, multiValArgs, duplicateKey);

  list.clear();
  if (!parseFromArg) {
    // Flatten ;-lists in the arguments into a single list as was done
    // by the original function(CMAKE_PARSE_ARGUMENTS).
    for (; argIter != argEnd; ++argIter) {
      list.append(*argIter);
    }
  } else {
    cm::string_view mode = *args.begin();
    // in the PARSE_ARGV or PARSE_ARGN mode read the arguments from ARGC and
    // ARGV#
    std::string argc = status.GetMakefile().GetSafeDefinition("ARGC");
    unsigned long count;
    if (!cmStrToULong(argc, &count)) {
      status.GetMakefile().IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat(mode, " called with ARGC='", argc,
                 "' that is not an unsigned integer"));
      cmSystemTools::SetFatalErrorOccurred();
      return true;
    }

    if (mode == "PARSE_ARGN") {
      argStart = count - argnc;
    }

    for (unsigned long i = argStart; i < count; ++i) {
      std::string const argName{ cmStrCat("ARGV", i) };
      cmValue arg = status.GetMakefile().GetDefinition(argName);
      if (!arg) {
        status.GetMakefile().IssueMessage(
          MessageType::FATAL_ERROR,
          cmStrCat(mode, " called with ", argName, " not set"));
        cmSystemTools::SetFatalErrorOccurred();
        return true;
      }
      list.emplace_back(*arg);
    }
  }

  std::vector<cm::string_view> keywordsSeen;
  parser.BindParsedKeywords(keywordsSeen);

  // For single-value keywords, only the last instance matters, since it
  // determines the value stored. But if a keyword is repeated, it will be
  // added to this vector if _any_ instance is missing a value. If one of the
  // earlier instances is missing a value but the last one isn't, its presence
  // in this vector will be misleading.
  std::vector<cm::string_view> keywordsMissingValues;
  parser.BindKeywordsMissingValue(keywordsMissingValues);

  parser.Parse(list, &unparsed);

  PassParsedArguments(
    prefix, status.GetMakefile(), options, singleValArgs, multiValArgs,
    unparsed, options_set(keywordsSeen.begin(), keywordsSeen.end()),
    options_set(keywordsMissingValues.begin(), keywordsMissingValues.end()),
    parseFromArg);

  return true;
}
