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

#include "cmCxxModuleMetadata.h"

#include <algorithm>
#include <set>
#include <string>
#include <utility>

#include <cmext/string_view>

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

#include "cmsys/FStream.hxx"

#include "cmFileSet.h"
#include "cmFileSetMetadata.h"
#include "cmGeneratedFileStream.h"
#include "cmJSONState.h"
#include "cmListFileCache.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"

namespace {

bool JsonIsStringArray(Json::Value const& v)
{
  return v.isArray() &&
    std::all_of(v.begin(), v.end(),
                [](Json::Value const& it) { return it.isString(); });
}

bool ParsePreprocessorDefine(Json::Value& dval,
                             cmCxxModuleMetadata::PreprocessorDefineData& out,
                             cmJSONState* state)
{
  if (!dval.isObject()) {
    state->AddErrorAtValue("each entry in 'definitions' must be an object",
                           &dval);
    return false;
  }

  if (!dval.isMember("name") || !dval["name"].isString() ||
      dval["name"].asString().empty()) {
    state->AddErrorAtValue(
      "preprocessor definition requires a non-empty 'name'", &dval["name"]);
    return false;
  }
  out.Name = dval["name"].asString();

  if (dval.isMember("value")) {
    if (dval["value"].isString()) {
      out.Value = dval["value"].asString();
    } else if (!dval["value"].isNull()) {
      state->AddErrorAtValue(
        "'value' in preprocessor definition must be string or null",
        &dval["value"]);
      return false;
    }
  }

  if (dval.isMember("undef")) {
    if (!dval["undef"].isBool()) {
      state->AddErrorAtValue(
        "'undef' in preprocessor definition must be boolean", &dval["undef"]);
      return false;
    }
    out.Undef = dval["undef"].asBool();
  }

  return true;
}

bool ParseCMakeLocalArgumentsVendor(
  Json::Value& cmlav, cmCxxModuleMetadata::LocalArgumentsData& out,
  cmJSONState* state)
{

  if (!cmlav.isObject()) {
    state->AddErrorAtValue("'vendor' must be an object", &cmlav);
    return false;
  }

  if (cmlav.isMember("compile-options")) {
    if (!JsonIsStringArray(cmlav["compile-options"])) {
      state->AddErrorAtValue("'compile-options' must be an array of strings",
                             &cmlav["compile-options"]);
      return false;
    }
    for (auto const& s : cmlav["compile-options"]) {
      out.CompileOptions.push_back(s.asString());
    }
  }

  if (cmlav.isMember("compile-features")) {
    if (!JsonIsStringArray(cmlav["compile-features"])) {
      state->AddErrorAtValue("'compile-features' must be an array of strings",
                             &cmlav["compile-features"]);
      return false;
    }
    for (auto const& s : cmlav["compile-features"]) {
      out.CompileFeatures.push_back(s.asString());
    }
  }

  return true;
}

bool ParseLocalArguments(Json::Value& lav,
                         cmCxxModuleMetadata::LocalArgumentsData& out,
                         cmJSONState* state)
{
  if (!lav.isObject()) {
    state->AddErrorAtValue("'local-arguments' must be an object", &lav);
    return false;
  }

  if (lav.isMember("include-directories")) {
    if (!JsonIsStringArray(lav["include-directories"])) {
      state->AddErrorAtValue(
        "'include-directories' must be an array of strings",
        &lav["include-directories"]);
      return false;
    }
    for (auto const& s : lav["include-directories"]) {
      out.IncludeDirectories.push_back(s.asString());
    }
  }

  if (lav.isMember("system-include-directories")) {
    if (!JsonIsStringArray(lav["system-include-directories"])) {
      state->AddErrorAtValue(
        "'system-include-directories' must be an array of strings",
        &lav["system-include-directories"]);
      return false;
    }
    for (auto const& s : lav["system-include-directories"]) {
      out.SystemIncludeDirectories.push_back(s.asString());
    }
  }

  if (lav.isMember("definitions")) {
    if (!lav["definitions"].isArray()) {
      state->AddErrorAtValue("'definitions' must be an array",
                             &lav["definitions"]);
      return false;
    }
    for (Json::Value& dval : lav["definitions"]) {
      out.Definitions.emplace_back();
      if (!ParsePreprocessorDefine(dval, out.Definitions.back(), state)) {
        return false;
      }
    }
  }

  if (lav.isMember("vendor")) {
    if (!ParseCMakeLocalArgumentsVendor(lav["vendor"], out, state)) {
      return false;
    }
  }

  return true;
}

bool ParseModule(Json::Value& mval, cmCxxModuleMetadata::ModuleData& mod,
                 cmJSONState* state)
{
  if (!mval.isObject()) {
    state->AddErrorAtValue("each entry in 'modules' must be an object", &mval);
    return false;
  }

  if (!mval.isMember("logical-name") || !mval["logical-name"].isString() ||
      mval["logical-name"].asString().empty()) {
    state->AddErrorAtValue(
      "module entries require a non-empty 'logical-name' string",
      &mval["logical-name"]);
    return false;
  }
  mod.LogicalName = mval["logical-name"].asString();

  if (!mval.isMember("source-path") || !mval["source-path"].isString() ||
      mval["source-path"].asString().empty()) {
    state->AddErrorAtValue(
      "module entries require a non-empty 'source-path' string",
      &mval["source-path"]);
    return false;
  }
  mod.SourcePath = mval["source-path"].asString();

  if (mval.isMember("is-interface")) {
    if (!mval["is-interface"].isBool()) {
      state->AddErrorAtValue("'is-interface' must be boolean",
                             &mval["is-interface"]);
      return false;
    }
    mod.IsInterface = mval["is-interface"].asBool();
  } else {
    mod.IsInterface = true;
  }

  if (mval.isMember("is-std-library")) {
    if (!mval["is-std-library"].isBool()) {
      state->AddErrorAtValue("'is-std-library' must be boolean",
                             &mval["is-std-library"]);
      return false;
    }
    mod.IsStdLibrary = mval["is-std-library"].asBool();
  } else {
    mod.IsStdLibrary = false;
  }

  if (mval.isMember("local-arguments")) {
    mod.LocalArguments.emplace();
    if (!ParseLocalArguments(mval["local-arguments"], *mod.LocalArguments,
                             state)) {
      return false;
    }
  }

  return true;
}

bool ParseRoot(Json::Value& root, cmCxxModuleMetadata& meta,
               cmJSONState* state)
{
  if (!root.isMember("version") || !root["version"].isInt()) {
    state->AddErrorAtValue(
      "Top-level member 'version' is required and must be an integer", &root);
    return false;
  }
  meta.Version = root["version"].asInt();

  if (root.isMember("revision")) {
    if (!root["revision"].isInt()) {
      state->AddErrorAtValue("'revision' must be an integer",
                             &root["revision"]);
      return false;
    }
    meta.Revision = root["revision"].asInt();
  }

  if (meta.Version != 1) {
    state->AddErrorAtValue(cmStrCat("Module manifest version number, '",
                                    meta.Version, '.', meta.Revision,
                                    "' is newer than max supported (1.1)"),
                           &root);
    return false;
  }

  if (root.isMember("modules")) {
    if (!root["modules"].isArray()) {
      state->AddErrorAtValue("'modules' must be an array", &root["modules"]);
      return false;
    }
    for (Json::Value& mval : root["modules"]) {
      meta.Modules.emplace_back();
      if (!ParseModule(mval, meta.Modules.back(), state)) {
        return false;
      }
    }
  }

  return true;
}

} // namespace

cmCxxModuleMetadata::ParseResult cmCxxModuleMetadata::LoadFromFile(
  std::string const& path)
{
  ParseResult res;

  Json::Value root;
  cmJSONState parseState(path, &root);
  if (!parseState.errors.empty()) {
    res.Error = parseState.GetErrorMessage();
    return res;
  }

  cmCxxModuleMetadata meta;
  if (!ParseRoot(root, meta, &parseState)) {
    res.Error = parseState.GetErrorMessage();
    return res;
  }

  meta.MetadataFilePath = path;
  res.Meta = std::move(meta);
  return res;
}

namespace {

Json::Value SerializePreprocessorDefine(
  cmCxxModuleMetadata::PreprocessorDefineData const& d)
{
  Json::Value dv(Json::objectValue);
  dv["name"] = d.Name;
  if (d.Value) {
    dv["value"] = *d.Value;
  }
  if (d.Undef) {
    dv["undef"] = d.Undef;
  }
  return dv;
}

Json::Value SerializeCMakeLocalArgumentsVendor(
  cmCxxModuleMetadata::LocalArgumentsData const& la)
{
  Json::Value vend(Json::objectValue);

  if (!la.CompileOptions.empty()) {
    Json::Value& opts = vend["compile-options"] = Json::arrayValue;
    for (auto const& s : la.CompileOptions) {
      opts.append(s);
    }
  }

  if (!la.CompileFeatures.empty()) {
    Json::Value& feats = vend["compile-features"] = Json::arrayValue;
    for (auto const& s : la.CompileFeatures) {
      feats.append(s);
    }
  }

  return vend;
}

Json::Value SerializeLocalArguments(
  cmCxxModuleMetadata::LocalArgumentsData const& la)
{
  Json::Value lav(Json::objectValue);

  if (!la.IncludeDirectories.empty()) {
    Json::Value& inc = lav["include-directories"] = Json::arrayValue;
    for (auto const& s : la.IncludeDirectories) {
      inc.append(s);
    }
  }

  if (!la.SystemIncludeDirectories.empty()) {
    Json::Value& sinc = lav["system-include-directories"] = Json::arrayValue;
    for (auto const& s : la.SystemIncludeDirectories) {
      sinc.append(s);
    }
  }

  if (!la.Definitions.empty()) {
    Json::Value& defs = lav["definitions"] = Json::arrayValue;
    for (auto const& d : la.Definitions) {
      defs.append(SerializePreprocessorDefine(d));
    }
  }

  Json::Value vend = SerializeCMakeLocalArgumentsVendor(la);
  if (!vend.empty()) {
    Json::Value& cmvend = lav["vendor"] = Json::objectValue;
    cmvend["cmake"] = std::move(vend);
  }

  return lav;
}

Json::Value SerializeModule(std::string& manifestRoot,
                            cmCxxModuleMetadata::ModuleData const& m)
{
  Json::Value mv(Json::objectValue);
  mv["logical-name"] = m.LogicalName;
  if (cmSystemTools::FileIsFullPath(m.SourcePath)) {
    mv["source-path"] = m.SourcePath;
  } else {
    mv["source-path"] = cmSystemTools::ForceToRelativePath(
      manifestRoot, cmStrCat('/', m.SourcePath));
  }
  mv["is-interface"] = m.IsInterface;
  mv["is-std-library"] = m.IsStdLibrary;

  if (m.LocalArguments) {
    mv["local-arguments"] = SerializeLocalArguments(*m.LocalArguments);
  }

  return mv;
}

} // namespace

Json::Value cmCxxModuleMetadata::ToJsonValue(cmCxxModuleMetadata const& meta)
{
  Json::Value root(Json::objectValue);

  root["version"] = meta.Version;
  root["revision"] = meta.Revision;

  Json::Value& modules = root["modules"] = Json::arrayValue;
  std::string manifestRoot =
    cmSystemTools::GetFilenamePath(meta.MetadataFilePath);

  if (!cmSystemTools::FileIsFullPath(meta.MetadataFilePath)) {
    manifestRoot = cmStrCat('/', manifestRoot);
  }

  for (auto const& m : meta.Modules) {
    modules.append(SerializeModule(manifestRoot, m));
  }

  return root;
}

cmCxxModuleMetadata::SaveResult cmCxxModuleMetadata::SaveToFile(
  std::string const& path, cmCxxModuleMetadata const& meta)
{
  SaveResult st;

  cmGeneratedFileStream ofs(path);
  if (!ofs.is_open()) {
    st.Error = "Unable to open temp file for writing";
    return st;
  }

  Json::StreamWriterBuilder wbuilder;
  wbuilder["indentation"] = "  ";
  ofs << Json::writeString(wbuilder, ToJsonValue(meta));

  ofs.Close();

  if (!ofs.good()) {
    st.Error = cmStrCat("Write failed for file: "_s, path);
    return st;
  }

  st.Ok = true;
  return st;
}

namespace {

struct MetaDataProperties
{
  std::string MetadataDir;
  std::set<cm::string_view> AllCompileFeatures;
  std::set<cm::string_view> AllCompileOptions;
  std::set<std::string> AllIncludeDirectories;
  std::set<std::string> AllCompileDefinitions;
  std::set<std::string> BaseDirs;
  std::set<std::string> Sources;

  std::string NormalizePath(std::string const& in) const
  {
    std::string out = in;
    if (!cmSystemTools::FileIsFullPath(in)) {
      out = cmStrCat(MetadataDir, '/', in);
    }
    return cmSystemTools::CollapseFullPath(out);
  }
};

MetaDataProperties CollectMetaProperties(cmCxxModuleMetadata const& meta)
{
  MetaDataProperties props;

  props.MetadataDir = cmSystemTools::GetFilenamePath(meta.MetadataFilePath);

  for (auto const& module : meta.Modules) {
    std::string sourcePath = props.NormalizePath(module.SourcePath);
    props.Sources.insert(sourcePath);

    // Module metadata files can reference files in different roots,
    // just use the immediate parent directory as a base directory
    props.BaseDirs.insert(cmSystemTools::GetFilenamePath(sourcePath));

    if (module.LocalArguments) {
      for (auto const& incDir : module.LocalArguments->IncludeDirectories) {
        props.AllIncludeDirectories.emplace(props.NormalizePath(incDir));
      }
      for (auto const& sysIncDir :
           module.LocalArguments->SystemIncludeDirectories) {
        props.AllIncludeDirectories.emplace(props.NormalizePath(sysIncDir));
      }
      for (auto const& opt : module.LocalArguments->CompileOptions) {
        props.AllCompileOptions.emplace(opt);
      }
      for (auto const& opt : module.LocalArguments->CompileFeatures) {
        props.AllCompileFeatures.emplace(opt);
      }

      for (auto const& def : module.LocalArguments->Definitions) {
        if (!def.Undef) {
          if (def.Value) {
            props.AllCompileDefinitions.emplace(
              cmStrCat(def.Name, "="_s, *def.Value));
          } else {
            props.AllCompileDefinitions.emplace(def.Name);
          }
        }
      }
    }
  }

  return props;
}

void PopulateFileSet(cmTarget& target, MetaDataProperties const& props)
{
  auto fileSet =
    target.GetOrCreateFileSet(std::string{ cm::FileSetMetadata::CXX_MODULES },
                              std::string{ cm::FileSetMetadata::CXX_MODULES },
                              cm::FileSetMetadata::Visibility::Public);

  for (auto const& source : props.Sources) {
    fileSet.first->AddFileEntry(source);
  }

  for (auto const& baseDir : props.BaseDirs) {
    fileSet.first->AddDirectoryEntry(baseDir);
  }
}

void PopulateLocalTarget(cmTarget& target, MetaDataProperties const& props)
{
  if (!props.AllIncludeDirectories.empty()) {
    target.AppendProperty("INCLUDE_DIRECTORIES",
                          cmJoin(props.AllIncludeDirectories, ";"));
  }

  if (!props.AllCompileDefinitions.empty()) {
    target.AppendProperty("COMPILE_DEFINITIONS",
                          cmJoin(props.AllCompileDefinitions, ";"));
  }

  if (!props.AllCompileOptions.empty()) {
    target.AppendProperty("COMPILE_OPTIONS",
                          cmJoin(props.AllCompileOptions, ";"));
  }

  if (!props.AllCompileFeatures.empty()) {
    target.AppendProperty("COMPILE_FEATURES",
                          cmJoin(props.AllCompileFeatures, ";"));
  }
}

void PopulateImportedTarget(cmTarget& target, MetaDataProperties const& props,
                            cmCxxModuleMetadata const& meta,
                            std::vector<std::string> const& configs)
{
  if (!props.AllIncludeDirectories.empty()) {
    target.SetProperty("IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES",
                       cmJoin(props.AllIncludeDirectories, ";"));
  }

  if (!props.AllCompileDefinitions.empty()) {
    target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS",
                       cmJoin(props.AllCompileDefinitions, ";"));
  }

  if (!props.AllCompileOptions.empty()) {
    target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_OPTIONS",
                       cmJoin(props.AllCompileOptions, ";"));
  }

  if (!props.AllCompileFeatures.empty()) {
    target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_FEATURES",
                       cmJoin(props.AllCompileFeatures, ";"));
  }

  for (auto const& config : configs) {
    std::vector<std::string> moduleList;
    for (auto const& module : meta.Modules) {
      if (module.IsInterface) {
        moduleList.push_back(cmStrCat(module.LogicalName, "="_s,
                                      props.NormalizePath(module.SourcePath)));
      }
    }

    if (!moduleList.empty()) {
      std::string upperConfig = cmSystemTools::UpperCase(config);
      std::string propertyName =
        cmStrCat("IMPORTED_CXX_MODULES_"_s, upperConfig);
      target.SetProperty(propertyName, cmJoin(moduleList, ";"));
    }
  }
}

} // namespace

void cmCxxModuleMetadata::PopulateTarget(
  cmTarget& target, cmCxxModuleMetadata const& meta,
  std::vector<std::string> const& configs)
{
  auto props = CollectMetaProperties(meta);
  PopulateFileSet(target, props);

  if (target.IsImported()) {
    PopulateImportedTarget(target, props, meta, configs);
  } else {
    PopulateLocalTarget(target, props);
  }
}
