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

#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <functional>
#include <set>

#include <cmext/string_view>

#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmExperimental.h"
#include "cmInstrumentation.h"
#include "cmInstrumentationQuery.h"
#include "cmMakefile.h"
#include "cmStringAlgorithms.h"
#include "cmake.h"

namespace {

bool isCharDigit(char ch)
{
  return std::isdigit(static_cast<unsigned char>(ch));
}
bool validateVersion(std::string const& key, std::string const& versionString,
                     int& version, cmExecutionStatus& status)
{
  if (!std::all_of(versionString.begin(), versionString.end(), isCharDigit)) {
    status.SetError(cmStrCat("given a non-integer ", key, "."));
    return false;
  }
  version = std::atoi(versionString.c_str());
  if (version != 1) {
    status.SetError(cmStrCat(
      "QUERY subcommand given an unsupported ", key, " \"", versionString,
      "\" (the only currently supported version is 1)."));
    return false;
  }
  return true;
}

template <typename E>
std::function<bool(std::string const&, E&)> EnumParser(
  std::vector<std::string> const toString)
{
  return [toString](std::string const& value, E& out) -> bool {
    for (size_t i = 0; i < toString.size(); ++i) {
      if (value == toString[i]) {
        out = (E)i;
        return true;
      }
    }
    return false;
  };
}
}

bool cmInstrumentationCommand(std::vector<std::string> const& args,
                              cmExecutionStatus& status)
{
  // if (status->GetMakefile().GetPropertyKeys) {
  if (!cmExperimental::HasSupportEnabled(
        status.GetMakefile(), cmExperimental::Feature::Instrumentation)) {
    status.SetError(
      "requires the experimental Instrumentation flag to be enabled");
    return false;
  }

  if (args.empty()) {
    status.SetError("must be called with arguments.");
    return false;
  }

  struct Arguments : public ArgumentParser::ParseResult
  {
    ArgumentParser::NonEmpty<std::string> ApiVersion;
    ArgumentParser::NonEmpty<std::string> DataVersion;
    ArgumentParser::NonEmpty<std::vector<std::string>> Queries;
    ArgumentParser::NonEmpty<std::vector<std::string>> Hooks;
    ArgumentParser::NonEmpty<std::vector<std::vector<std::string>>> Callbacks;
  };

  static auto const parser = cmArgumentParser<Arguments>{}
                               .Bind("API_VERSION"_s, &Arguments::ApiVersion)
                               .Bind("DATA_VERSION"_s, &Arguments::DataVersion)
                               .Bind("QUERIES"_s, &Arguments::Queries)
                               .Bind("HOOKS"_s, &Arguments::Hooks)
                               .Bind("CALLBACK"_s, &Arguments::Callbacks);

  std::vector<std::string> unparsedArguments;
  Arguments const arguments = parser.Parse(args, &unparsedArguments);

  if (arguments.MaybeReportError(status.GetMakefile())) {
    return true;
  }
  if (!unparsedArguments.empty()) {
    status.SetError("given unknown argument \"" + unparsedArguments.front() +
                    "\".");
    return false;
  }
  int apiVersion;
  int dataVersion;
  if (!validateVersion("API_VERSION", arguments.ApiVersion, apiVersion,
                       status) ||
      !validateVersion("DATA_VERSION", arguments.DataVersion, dataVersion,
                       status)) {
    return false;
  }

  std::set<cmInstrumentationQuery::Query> queries;
  auto queryParser = EnumParser<cmInstrumentationQuery::Query>(
    cmInstrumentationQuery::QueryString);
  for (auto const& arg : arguments.Queries) {
    cmInstrumentationQuery::Query query;
    if (!queryParser(arg, query)) {
      status.SetError(
        cmStrCat("given invalid argument to QUERIES \"", arg, "\""));
      return false;
    }
    queries.insert(query);
  }

  std::set<cmInstrumentationQuery::Hook> hooks;
  auto hookParser = EnumParser<cmInstrumentationQuery::Hook>(
    cmInstrumentationQuery::HookString);
  for (auto const& arg : arguments.Hooks) {
    cmInstrumentationQuery::Hook hook;
    if (!hookParser(arg, hook)) {
      status.SetError(
        cmStrCat("given invalid argument to HOOKS \"", arg, "\""));
      return false;
    }
    hooks.insert(hook);
  }

  status.GetMakefile()
    .GetCMakeInstance()
    ->GetInstrumentation()
    ->WriteJSONQuery(queries, hooks, arguments.Callbacks);

  return true;
}
