/* 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/reader.h>
#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 "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") {
      Json::CharReaderBuilder builder;
      std::istringstream iss(contentString);
      if (!Json::parseFromStream(builder, iss, &value, nullptr)) {
        status.SetError(
          cmStrCat("failed to parse custom content as JSON: ", contentString));
        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;
}
