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

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

#include <cmext/string_view>

#include <cm3p/json/value.h>

#include "cmsys/String.h"

#include "cmArgumentParser.h"
#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmInstrumentation.h"
#include "cmInstrumentationQuery.h"
#include "cmJSONState.h"
#include "cmList.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmValue.h"
#include "cmake.h"

namespace {

using Version = cmInstrumentationQuery::Version;

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

bool validateDataVersion(std::string const& versionString, Version& version,
                         cmExecutionStatus& status)
{
  char const* vStart = versionString.c_str();
  if (!std::all_of(versionString.begin(), versionString.end(), [](char c) {
        return cmsysString_isdigit(c) || c == '.';
      })) {
    status.SetError(
      cmStrCat("given a malformed DATA_VERSION \"", versionString,
               "\". A numeric major or major.minor version is required."));

    return false;
  }

  version.Major = std::atoi(vStart);
  version.Minor = 0;
  std::string::size_type pos = versionString.find('.');
  if (pos != std::string::npos) {
    vStart += pos + 1;
    version.Minor = std::atoi(vStart);
  }

  if (version.Major < 1 || version.Minor < 0) {
    status.SetError(
      cmStrCat("given a malformed DATA_VERSION \"", versionString,
               "\". A numeric major or major.minor version is required."));
    return false;
  }

  if (!cmInstrumentationQuery::ValidDataVersion(version)) {
    status.SetError(
      cmStrCat("given an unsupported DATA_VERSION \"", versionString,
               "\" (the maximum currently supported version is 1.2)."));
    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 (args.empty()) {
    status.SetError("must be called with arguments.");
    return false;
  }

  if (status.GetMakefile().GetCMakeInstance()->GetInInitialCache()) {
    status.GetMakefile().IssueMessage(
      MessageType::FATAL_ERROR,
      "Cannot invoke cmake_instrumentation() within an initial cache file.");
    return false;
  }

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

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

  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;
  Version dataVersion;
  if (!validateVersion("API_VERSION", arguments.ApiVersion, apiVersion,
                       status) ||
      !validateDataVersion(arguments.DataVersion, dataVersion, status)) {
    return false;
  }

  std::set<cmInstrumentationQuery::Option> options;
  auto optionParser = EnumParser<cmInstrumentationQuery::Option>(
    cmInstrumentationQuery::OptionString);
  for (auto const& arg : arguments.Options) {
    cmInstrumentationQuery::Option option;
    if (!optionParser(arg, option)) {
      status.SetError(
        cmStrCat("given invalid argument to OPTIONS \"", arg, '"'));
      return false;
    }
    options.insert(option);
  }

  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);
  }

  // Generate custom content
  cmInstrumentation* instrumentation =
    status.GetMakefile().GetCMakeInstance()->GetInstrumentation();
  for (auto const& content : arguments.CustomContent) {
    if (content.size() != 3) {
      status.SetError("CUSTOM_CONTENT expected 3 arguments");
      return false;
    }
    std::string const label = content[0];
    std::string const type = content[1];
    std::string const contentString = content[2];
    Json::Value value;
    if (type == "STRING") {
      value = contentString;
    } else if (type == "BOOL") {
      value = !cmValue(contentString).IsOff();
    } else if (type == "LIST") {
      value = Json::arrayValue;
      for (auto const& item : cmList(contentString)) {
        value.append(item);
      }
    } else if (type == "JSON") {
      std::istringstream iss(contentString);
      cmJSONState parseState(iss, &value, cmJSONState::StrictMode::Relaxed);
      if (!parseState.errors.empty()) {
        status.SetError(cmStrCat("failed to parse custom content as JSON:\n ",
                                 parseState.GetErrorMessage()));
        return false;
      }
    } else {
      status.SetError(
        cmStrCat("got an invalid type for CUSTOM_CONTENT: ", type));
      return false;
    }
    instrumentation->AddCustomContent(content.front(), value);
  }

  // Write query file
  instrumentation->WriteJSONQuery(dataVersion, options, hooks,
                                  arguments.Callbacks);

  return true;
}
