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

#include "cmScanDepFormat.h"

#include <cctype>
#include <cstdio>
#include <iostream>
#include <utility>

#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
#include <cm3p/json/writer.h>

#include "cmsys/FStream.hxx"

#include "cmGeneratedFileStream.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

static bool ParseFilename(Json::Value const& val, std::string& result)
{
  if (val.isString()) {
    result = val.asString();
  } else {
    return false;
  }

  return true;
}

static Json::Value EncodeFilename(std::string const& path)
{
  std::string data;
  data.reserve(path.size());

  for (auto const& byte : path) {
    if (std::iscntrl(byte)) {
      // Control characters.
      data.append("\\u");
      char buf[5];
      std::snprintf(buf, sizeof(buf), "%04x", byte);
      data.append(buf);
    } else if (byte == '"' || byte == '\\') {
      // Special JSON characters.
      data.push_back('\\');
      data.push_back(byte);
    } else {
      // Other data.
      data.push_back(byte);
    }
  }

  return data;
}

#define PARSE_BLOB(val, res)                                                  \
  do {                                                                        \
    if (!ParseFilename(val, res)) {                                           \
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \
                                    arg_pp, ": invalid blob"));               \
      return false;                                                           \
    }                                                                         \
  } while (0)

#define PARSE_FILENAME(val, res)                                              \
  do {                                                                        \
    if (!ParseFilename(val, res)) {                                           \
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", \
                                    arg_pp, ": invalid filename"));           \
      return false;                                                           \
    }                                                                         \
                                                                              \
    if (work_directory && !work_directory->empty() &&                         \
        !cmSystemTools::FileIsFullPath(res)) {                                \
      res = cmStrCat(*work_directory, '/', res);                              \
    }                                                                         \
  } while (0)

bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp,
                                 cmScanDepInfo* info)
{
  Json::Value ppio;
  Json::Value const& ppi = ppio;
  cmsys::ifstream ppf(arg_pp.c_str(), std::ios::in | std::ios::binary);
  {
    Json::Reader reader;
    if (!reader.parse(ppf, ppio, false)) {
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                    arg_pp,
                                    reader.getFormattedErrorMessages()));
      return false;
    }
  }

  Json::Value const& version = ppi["version"];
  if (version.asUInt() > 1) {
    cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                  arg_pp, ": version ", version.asString()));
    return false;
  }

  Json::Value const& rules = ppi["rules"];
  if (rules.isArray()) {
    if (rules.size() != 1) {
      cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                    arg_pp, ": expected 1 source entry"));
      return false;
    }

    for (auto const& rule : rules) {
      cm::optional<std::string> work_directory;
      Json::Value const& workdir = rule["work-directory"];
      if (workdir.isString()) {
        std::string wd;
        PARSE_BLOB(workdir, wd);
        work_directory = std::move(wd);
      } else if (!workdir.isNull()) {
        cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
                                      arg_pp,
                                      ": work-directory is not a string"));
        return false;
      }

      if (rule.isMember("primary-output")) {
        Json::Value const& primary_output = rule["primary-output"];
        PARSE_FILENAME(primary_output, info->PrimaryOutput);
      }

      if (rule.isMember("outputs")) {
        Json::Value const& outputs = rule["outputs"];
        if (outputs.isArray()) {
          for (auto const& output : outputs) {
            std::string extra_output;
            PARSE_FILENAME(output, extra_output);

            info->ExtraOutputs.emplace_back(extra_output);
          }
        }
      }

      if (rule.isMember("provides")) {
        Json::Value const& provides = rule["provides"];
        if (!provides.isArray()) {
          cmSystemTools::Error(
            cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                     ": provides is not an array"));
          return false;
        }

        for (auto const& provide : provides) {
          cmSourceReqInfo provide_info;

          Json::Value const& logical_name = provide["logical-name"];
          PARSE_BLOB(logical_name, provide_info.LogicalName);

          if (provide.isMember("compiled-module-path")) {
            Json::Value const& compiled_module_path =
              provide["compiled-module-path"];
            PARSE_FILENAME(compiled_module_path,
                           provide_info.CompiledModulePath);
          }

          if (provide.isMember("unique-on-source-path")) {
            Json::Value const& unique_on_source_path =
              provide["unique-on-source-path"];
            if (!unique_on_source_path.isBool()) {
              cmSystemTools::Error(
                cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                         ": unique-on-source-path is not a boolean"));
              return false;
            }
            provide_info.UseSourcePath = unique_on_source_path.asBool();
          } else {
            provide_info.UseSourcePath = false;
          }

          if (provide.isMember("source-path")) {
            Json::Value const& source_path = provide["source-path"];
            PARSE_FILENAME(source_path, provide_info.SourcePath);
          } else if (provide_info.UseSourcePath) {
            cmSystemTools::Error(
              cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                       ": source-path is missing"));
            return false;
          }

          if (provide.isMember("is-interface")) {
            Json::Value const& is_interface = provide["is-interface"];
            if (!is_interface.isBool()) {
              cmSystemTools::Error(
                cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                         ": is-interface is not a boolean"));
              return false;
            }
            provide_info.IsInterface = is_interface.asBool();
          } else {
            provide_info.IsInterface = true;
          }

          info->Provides.push_back(provide_info);
        }
      }

      if (rule.isMember("requires")) {
        Json::Value const& reqs = rule["requires"];
        if (!reqs.isArray()) {
          cmSystemTools::Error(
            cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                     ": requires is not an array"));
          return false;
        }

        for (auto const& require : reqs) {
          cmSourceReqInfo require_info;

          Json::Value const& logical_name = require["logical-name"];
          PARSE_BLOB(logical_name, require_info.LogicalName);

          if (require.isMember("compiled-module-path")) {
            Json::Value const& compiled_module_path =
              require["compiled-module-path"];
            PARSE_FILENAME(compiled_module_path,
                           require_info.CompiledModulePath);
          }

          if (require.isMember("unique-on-source-path")) {
            Json::Value const& unique_on_source_path =
              require["unique-on-source-path"];
            if (!unique_on_source_path.isBool()) {
              cmSystemTools::Error(
                cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                         ": unique-on-source-path is not a boolean"));
              return false;
            }
            require_info.UseSourcePath = unique_on_source_path.asBool();
          } else {
            require_info.UseSourcePath = false;
          }

          if (require.isMember("source-path")) {
            Json::Value const& source_path = require["source-path"];
            PARSE_FILENAME(source_path, require_info.SourcePath);
          } else if (require_info.UseSourcePath) {
            cmSystemTools::Error(
              cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                       ": source-path is missing"));
            return false;
          }

          if (require.isMember("lookup-method")) {
            Json::Value const& lookup_method = require["lookup-method"];
            if (!lookup_method.isString()) {
              cmSystemTools::Error(
                cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                         ": lookup-method is not a string"));
              return false;
            }

            std::string lookup_method_str = lookup_method.asString();
            if (lookup_method_str == "by-name"_s) {
              require_info.Method = LookupMethod::ByName;
            } else if (lookup_method_str == "include-angle"_s) {
              require_info.Method = LookupMethod::IncludeAngle;
            } else if (lookup_method_str == "include-quote"_s) {
              require_info.Method = LookupMethod::IncludeQuote;
            } else {
              cmSystemTools::Error(cmStrCat(
                "-E cmake_ninja_dyndep failed to parse ", arg_pp,
                ": lookup-method is not a valid: ", lookup_method_str));
              return false;
            }
          } else if (require_info.UseSourcePath) {
            require_info.Method = LookupMethod::ByName;
          }

          info->Requires.push_back(require_info);
        }
      }

      // MSVC 17.3 toolchain bug. Remove when 17.4 is available.
      if (rule.isMember("is-interface")) {
        std::cerr
          << "warning: acknowledging an VS 17.3 toolchain bug; accepting "
             "until a new release which fixes it is available"
          << std::endl;

        Json::Value const& is_interface_json = rule["is-interface"];
        if (!is_interface_json.isBool()) {
          cmSystemTools::Error(
            cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                     ": is-interface is not a boolean"));
          return false;
        }
        bool is_interface = is_interface_json.asBool();

        for (auto& provide : info->Provides) {
          provide.IsInterface = is_interface;
        }
      }
    }
  }

  return true;
}

bool cmScanDepFormat_P1689_Write(std::string const& path,
                                 cmScanDepInfo const& info)
{
  Json::Value ddi(Json::objectValue);
  ddi["version"] = 0;
  ddi["revision"] = 0;

  Json::Value& rules = ddi["rules"] = Json::arrayValue;

  Json::Value rule(Json::objectValue);

  rule["primary-output"] = EncodeFilename(info.PrimaryOutput);

  Json::Value& rule_outputs = rule["outputs"] = Json::arrayValue;
  for (auto const& output : info.ExtraOutputs) {
    rule_outputs.append(EncodeFilename(output));
  }

  Json::Value& provides = rule["provides"] = Json::arrayValue;
  for (auto const& provide : info.Provides) {
    Json::Value provide_obj(Json::objectValue);
    auto const encoded = EncodeFilename(provide.LogicalName);
    provide_obj["logical-name"] = encoded;
    if (!provide.CompiledModulePath.empty()) {
      provide_obj["compiled-module-path"] =
        EncodeFilename(provide.CompiledModulePath);
    }

    if (provide.UseSourcePath) {
      provide_obj["unique-on-source-path"] = true;
      provide_obj["source-path"] = EncodeFilename(provide.SourcePath);
    } else if (!provide.SourcePath.empty()) {
      provide_obj["source-path"] = EncodeFilename(provide.SourcePath);
    }

    provide_obj["is-interface"] = provide.IsInterface;

    provides.append(provide_obj);
  }

  Json::Value& reqs = rule["requires"] = Json::arrayValue;
  for (auto const& require : info.Requires) {
    Json::Value require_obj(Json::objectValue);
    auto const encoded = EncodeFilename(require.LogicalName);
    require_obj["logical-name"] = encoded;
    if (!require.CompiledModulePath.empty()) {
      require_obj["compiled-module-path"] =
        EncodeFilename(require.CompiledModulePath);
    }

    if (require.UseSourcePath) {
      require_obj["unique-on-source-path"] = true;
      require_obj["source-path"] = EncodeFilename(require.SourcePath);
    } else if (!require.SourcePath.empty()) {
      require_obj["source-path"] = EncodeFilename(require.SourcePath);
    }

    const char* lookup_method = nullptr;
    switch (require.Method) {
      case LookupMethod::ByName:
        // No explicit value needed for the default.
        break;
      case LookupMethod::IncludeAngle:
        lookup_method = "include-angle";
        break;
      case LookupMethod::IncludeQuote:
        lookup_method = "include-quote";
        break;
    }
    if (lookup_method) {
      require_obj["lookup-method"] = lookup_method;
    }

    reqs.append(require_obj);
  }

  rules.append(rule);

  cmGeneratedFileStream ddif(path);
  ddif << ddi;

  return !!ddif;
}
