/* 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 <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.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() != 0) {
    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) {
      std::string work_directory;
      Json::Value const& workdir = rule["work-directory"];
      if (workdir.isString()) {
        PARSE_BLOB(workdir, work_directory);
      } 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("future-compile")) {
        Json::Value const& future_compile = rule["future-compile"];

        if (future_compile.isMember("outputs")) {
          Json::Value const& outputs = future_compile["outputs"];
          if (outputs.isArray()) {
            if (outputs.empty()) {
              cmSystemTools::Error(
                cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp,
                         ": expected at least one 1 output"));
              return false;
            }

            PARSE_FILENAME(outputs[0], info->PrimaryOutput);
          }
        }

        if (future_compile.isMember("provides")) {
          Json::Value const& provides = future_compile["provides"];
          if (provides.isArray()) {
            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);
              } else {
                provide_info.CompiledModulePath =
                  cmStrCat(provide_info.LogicalName, ".mod");
              }

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

        if (future_compile.isMember("requires")) {
          Json::Value const& reqs = future_compile["requires"];
          if (reqs.isArray()) {
            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);
              }

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

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

  Json::Value& future_compile = rule["future-compile"] = Json::objectValue;

  Json::Value& outputs = future_compile["outputs"] = Json::arrayValue;
  outputs.append(info.PrimaryOutput);

  Json::Value& provides = future_compile["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"] = encoded;
    } else {
      provide_obj["compiled-module-path"] =
        EncodeFilename(provide.CompiledModulePath);
    }

    // TODO: Source file tracking. See below.

    provides.append(provide_obj);
  }

  Json::Value& reqs = future_compile["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"] = encoded;
    } else {
      require_obj["compiled-module-path"] =
        EncodeFilename(require.CompiledModulePath);
    }

    // TODO: Source filename inclusion. Requires collating with the provides
    // filenames (as a sanity check if available on both sides).

    reqs.append(require_obj);
  }

  rules.append(rule);

  cmGeneratedFileStream ddif(path);
  ddif << ddi;

  return !!ddif;
}
