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

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <cm3p/json/value.h>

#include "cmFileAPI.h"
#include "cmGlobCacheEntry.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmake.h"

namespace {

class CMakeFiles
{
  cmFileAPI& FileAPI;
  unsigned int Version;
  std::string CMakeModules;
  std::string const& TopSource;
  std::string const& TopBuild;
  bool OutOfSource;

  Json::Value DumpPaths();
  Json::Value DumpInputs();
  Json::Value DumpInput(std::string const& file);
  Json::Value DumpGlobsDependent();
  Json::Value DumpGlobDependent(cmGlobCacheEntry const& entry);

public:
  CMakeFiles(cmFileAPI& fileAPI, unsigned int version);
  Json::Value Dump();
};

CMakeFiles::CMakeFiles(cmFileAPI& fileAPI, unsigned int version)
  : FileAPI(fileAPI)
  , Version(version)
  , CMakeModules(cmSystemTools::GetCMakeRoot() + "/Modules")
  , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
  , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
  , OutOfSource(this->TopBuild != this->TopSource)
{
  static_cast<void>(this->Version);
}

Json::Value CMakeFiles::Dump()
{
  Json::Value cmakeFiles = Json::objectValue;
  cmakeFiles["paths"] = this->DumpPaths();
  cmakeFiles["inputs"] = this->DumpInputs();
  Json::Value globsDependent = this->DumpGlobsDependent();
  if (!globsDependent.empty()) {
    cmakeFiles["globsDependent"] = std::move(globsDependent);
  }
  return cmakeFiles;
}

Json::Value CMakeFiles::DumpPaths()
{
  Json::Value paths = Json::objectValue;
  paths["source"] = this->TopSource;
  paths["build"] = this->TopBuild;
  return paths;
}

Json::Value CMakeFiles::DumpInputs()
{
  Json::Value inputs = Json::arrayValue;

  cmGlobalGenerator* gg =
    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
  for (auto const& lg : gg->GetLocalGenerators()) {
    cmMakefile const* mf = lg->GetMakefile();
    for (std::string const& file : mf->GetListFiles()) {
      inputs.append(this->DumpInput(file));
    }
  }

  return inputs;
}

Json::Value CMakeFiles::DumpInput(std::string const& file)
{
  Json::Value input = Json::objectValue;

  bool const isCMake = cmSystemTools::IsSubDirectory(file, this->CMakeModules);
  if (isCMake) {
    input["isCMake"] = true;
  }

  if (!cmSystemTools::IsSubDirectory(file, this->TopSource) &&
      !cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
    input["isExternal"] = true;
  }

  if (this->OutOfSource &&
      cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
    input["isGenerated"] = true;
  }

  std::string path = file;
  if (!isCMake && cmSystemTools::IsSubDirectory(path, this->TopSource)) {
    // Use a relative path within the source directory.
    path = cmSystemTools::RelativePath(this->TopSource, path);
  }
  input["path"] = path;

  return input;
}

Json::Value CMakeFiles::DumpGlobsDependent()
{
  Json::Value globsDependent = Json::arrayValue;
  for (cmGlobCacheEntry const& entry :
       this->FileAPI.GetCMakeInstance()->GetGlobCacheEntries()) {
    globsDependent.append(this->DumpGlobDependent(entry));
  }
  return globsDependent;
}

Json::Value CMakeFiles::DumpGlobDependent(cmGlobCacheEntry const& entry)
{
  Json::Value globDependent = Json::objectValue;
  globDependent["expression"] = entry.Expression;
  if (entry.Recurse) {
    globDependent["recurse"] = true;
  }
  if (entry.ListDirectories) {
    globDependent["listDirectories"] = true;
  }
  if (entry.FollowSymlinks) {
    globDependent["followSymlinks"] = true;
  }
  if (!entry.Relative.empty()) {
    globDependent["relative"] = entry.Relative;
  }
  Json::Value paths = Json::arrayValue;
  for (std::string const& file : entry.Files) {
    paths.append(file);
  }
  globDependent["paths"] = std::move(paths);
  return globDependent;
}
}

Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, unsigned int version)
{
  CMakeFiles cmakeFiles(fileAPI, version);
  return cmakeFiles.Dump();
}
