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

#include <cstddef>
#include <iostream>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <utility>

#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"

namespace {
enum LinkLibraryScopeType
{
  LLT_SCOPE_PUBLIC,
  LLT_SCOPE_PRIVATE,
  LLT_SCOPE_INTERFACE
};

const char* const GRAPHVIZ_PRIVATE_EDEGE_STYLE = "dashed";
const char* const GRAPHVIZ_INTERFACE_EDEGE_STYLE = "dotted";

std::string getLinkLibraryStyle(const LinkLibraryScopeType& type)
{
  std::string style;
  switch (type) {
    case LLT_SCOPE_PRIVATE:
      style = "[style = " + std::string(GRAPHVIZ_PRIVATE_EDEGE_STYLE) + "]";
      break;
    case LLT_SCOPE_INTERFACE:
      style = "[style = " + std::string(GRAPHVIZ_INTERFACE_EDEGE_STYLE) + "]";
      break;
    default:
      break;
  }
  return style;
}

const char* getShapeForTarget(const cmGeneratorTarget* target)
{
  if (!target) {
    return "ellipse";
  }

  switch (target->GetType()) {
    case cmStateEnums::EXECUTABLE:
      return "house";
    case cmStateEnums::STATIC_LIBRARY:
      return "diamond";
    case cmStateEnums::SHARED_LIBRARY:
      return "polygon";
    case cmStateEnums::MODULE_LIBRARY:
      return "octagon";
    default:
      break;
  }

  return "box";
}

std::map<std::string, LinkLibraryScopeType> getScopedLinkLibrariesFromTarget(
  cmTarget* Target)
{
  char sep = ';';
  std::map<std::string, LinkLibraryScopeType> tokens;
  size_t start = 0, end = 0;

  const char* pInterfaceLinkLibraries =
    Target->GetProperty("INTERFACE_LINK_LIBRARIES");
  const char* pLinkLibraries = Target->GetProperty("LINK_LIBRARIES");

  if (!pInterfaceLinkLibraries && !pLinkLibraries) {
    return tokens; // target is not linked against any other libraries
  }

  // make sure we don't touch a null-ptr
  auto interfaceLinkLibraries =
    std::string(pInterfaceLinkLibraries ? pInterfaceLinkLibraries : "");
  auto linkLibraries = std::string(pLinkLibraries ? pLinkLibraries : "");

  // first extract interfaceLinkLibraries
  while (start < interfaceLinkLibraries.length()) {

    if ((end = interfaceLinkLibraries.find(sep, start)) == std::string::npos) {
      end = interfaceLinkLibraries.length();
    }

    std::string element = interfaceLinkLibraries.substr(start, end - start);
    if (std::string::npos == element.find("$<LINK_ONLY:", 0)) {
      // we assume first, that this library is an interface library.
      // if we find it again in the linklibraries property, we promote it to an
      // public library.
      tokens[element] = LLT_SCOPE_INTERFACE;
    } else {
      // this is an private linked static library.
      // we take care of this case in the second iterator.
    }
    start = end + 1;
  }

  // second extract linkLibraries
  start = 0;
  while (start < linkLibraries.length()) {

    if ((end = linkLibraries.find(sep, start)) == std::string::npos) {
      end = linkLibraries.length();
    }

    std::string element = linkLibraries.substr(start, end - start);

    if (tokens.find(element) == tokens.end()) {
      // this library is not found in interfaceLinkLibraries but in
      // linkLibraries.
      // this results in a private linked library.
      tokens[element] = LLT_SCOPE_PRIVATE;
    } else if (LLT_SCOPE_INTERFACE == tokens[element]) {
      // this library is found in interfaceLinkLibraries and linkLibraries.
      // this results in a public linked library.
      tokens[element] = LLT_SCOPE_PUBLIC;
    } else {
      // private and public linked libraries should not be changed anymore.
    }

    start = end + 1;
  }

  return tokens;
}
}

cmGraphVizWriter::cmGraphVizWriter(
  const std::vector<cmLocalGenerator*>& localGenerators)
  : GraphType("digraph")
  , GraphName("GG")
  , GraphHeader("node [\n  fontsize = \"12\"\n];")
  , GraphNodePrefix("node")
  , LocalGenerators(localGenerators)
  , GenerateForExecutables(true)
  , GenerateForStaticLibs(true)
  , GenerateForSharedLibs(true)
  , GenerateForModuleLibs(true)
  , GenerateForInterface(true)
  , GenerateForExternals(true)
  , GeneratePerTarget(true)
  , GenerateDependers(true)
  , HaveTargetsAndLibs(false)
{
}

void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
                                    const char* fallbackSettingsFileName)
{
  cmake cm(cmake::RoleScript);
  cm.SetHomeDirectory("");
  cm.SetHomeOutputDirectory("");
  cm.GetCurrentSnapshot().SetDefaultDefinitions();
  cmGlobalGenerator ggi(&cm);
  cmMakefile mf(&ggi, cm.GetCurrentSnapshot());
  std::unique_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator(&mf));

  const char* inFileName = settingsFileName;

  if (!cmSystemTools::FileExists(inFileName)) {
    inFileName = fallbackSettingsFileName;
    if (!cmSystemTools::FileExists(inFileName)) {
      return;
    }
  }

  if (!mf.ReadListFile(inFileName)) {
    cmSystemTools::Error("Problem opening GraphViz options file: ",
                         inFileName);
    return;
  }

  std::cout << "Reading GraphViz options file: " << inFileName << std::endl;

#define __set_if_set(var, cmakeDefinition)                                    \
  {                                                                           \
    const char* value = mf.GetDefinition(cmakeDefinition);                    \
    if (value) {                                                              \
      (var) = value;                                                          \
    }                                                                         \
  }

  __set_if_set(this->GraphType, "GRAPHVIZ_GRAPH_TYPE");
  __set_if_set(this->GraphName, "GRAPHVIZ_GRAPH_NAME");
  __set_if_set(this->GraphHeader, "GRAPHVIZ_GRAPH_HEADER");
  __set_if_set(this->GraphNodePrefix, "GRAPHVIZ_NODE_PREFIX");

#define __set_bool_if_set(var, cmakeDefinition)                               \
  {                                                                           \
    const char* value = mf.GetDefinition(cmakeDefinition);                    \
    if (value) {                                                              \
      (var) = mf.IsOn(cmakeDefinition);                                       \
    }                                                                         \
  }

  __set_bool_if_set(this->GenerateForExecutables, "GRAPHVIZ_EXECUTABLES");
  __set_bool_if_set(this->GenerateForStaticLibs, "GRAPHVIZ_STATIC_LIBS");
  __set_bool_if_set(this->GenerateForSharedLibs, "GRAPHVIZ_SHARED_LIBS");
  __set_bool_if_set(this->GenerateForModuleLibs, "GRAPHVIZ_MODULE_LIBS");
  __set_bool_if_set(this->GenerateForInterface, "GRAPHVIZ_INTERFACE");
  __set_bool_if_set(this->GenerateForExternals, "GRAPHVIZ_EXTERNAL_LIBS");
  __set_bool_if_set(this->GeneratePerTarget, "GRAPHVIZ_GENERATE_PER_TARGET");
  __set_bool_if_set(this->GenerateDependers, "GRAPHVIZ_GENERATE_DEPENDERS");

  std::string ignoreTargetsRegexes;
  __set_if_set(ignoreTargetsRegexes, "GRAPHVIZ_IGNORE_TARGETS");

  this->TargetsToIgnoreRegex.clear();
  if (!ignoreTargetsRegexes.empty()) {
    std::vector<std::string> ignoreTargetsRegExVector;
    cmSystemTools::ExpandListArgument(ignoreTargetsRegexes,
                                      ignoreTargetsRegExVector);
    for (std::string const& currentRegexString : ignoreTargetsRegExVector) {
      cmsys::RegularExpression currentRegex;
      if (!currentRegex.compile(currentRegexString)) {
        std::cerr << "Could not compile bad regex \"" << currentRegexString
                  << "\"" << std::endl;
      }
      this->TargetsToIgnoreRegex.push_back(std::move(currentRegex));
    }
  }
}

// Iterate over all targets and write for each one a graph which shows
// which other targets depend on it.
void cmGraphVizWriter::WriteTargetDependersFiles(const char* fileName)
{
  if (!this->GenerateDependers) {
    return;
  }

  this->CollectTargetsAndLibs();

  for (auto const& ptr : this->TargetPtrs) {
    if (ptr.second == nullptr) {
      continue;
    }

    if (!this->GenerateForTargetType(ptr.second->GetType())) {
      continue;
    }

    std::string currentFilename = fileName;
    currentFilename += ".";
    currentFilename += ptr.first;
    currentFilename += ".dependers";

    cmGeneratedFileStream str(currentFilename.c_str());
    if (!str) {
      return;
    }

    std::set<std::string> insertedConnections;
    std::set<std::string> insertedNodes;

    std::cout << "Writing " << currentFilename << "..." << std::endl;
    this->WriteHeader(str);

    this->WriteDependerConnections(ptr.first, insertedNodes,
                                   insertedConnections, str);

    this->WriteFooter(str);
  }
}

// Iterate over all targets and write for each one a graph which shows
// on which targets it depends.
void cmGraphVizWriter::WritePerTargetFiles(const char* fileName)
{
  if (!this->GeneratePerTarget) {
    return;
  }

  this->CollectTargetsAndLibs();

  for (auto const& ptr : this->TargetPtrs) {
    if (ptr.second == nullptr) {
      continue;
    }

    if (!this->GenerateForTargetType(ptr.second->GetType())) {
      continue;
    }

    std::set<std::string> insertedConnections;
    std::set<std::string> insertedNodes;

    std::string currentFilename = fileName;
    currentFilename += ".";
    currentFilename += ptr.first;
    cmGeneratedFileStream str(currentFilename.c_str());
    if (!str) {
      return;
    }

    std::cout << "Writing " << currentFilename << "..." << std::endl;
    this->WriteHeader(str);

    this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
    this->WriteFooter(str);
  }
}

void cmGraphVizWriter::WriteGlobalFile(const char* fileName)
{
  this->CollectTargetsAndLibs();

  cmGeneratedFileStream str(fileName);
  if (!str) {
    return;
  }
  this->WriteHeader(str);

  std::cout << "Writing " << fileName << "..." << std::endl;

  std::set<std::string> insertedConnections;
  std::set<std::string> insertedNodes;

  for (auto const& ptr : this->TargetPtrs) {
    if (ptr.second == nullptr) {
      continue;
    }

    if (!this->GenerateForTargetType(ptr.second->GetType())) {
      continue;
    }

    this->WriteConnections(ptr.first, insertedNodes, insertedConnections, str);
  }
  this->WriteFooter(str);
}

void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& str) const
{
  str << this->GraphType << " \"" << this->GraphName << "\" {" << std::endl;
  str << this->GraphHeader << std::endl;
}

void cmGraphVizWriter::WriteFooter(cmGeneratedFileStream& str) const
{
  str << "}" << std::endl;
}

void cmGraphVizWriter::WriteConnections(
  const std::string& targetName, std::set<std::string>& insertedNodes,
  std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
  std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
    this->TargetPtrs.find(targetName);

  if (targetPtrIt == this->TargetPtrs.end()) // not found at all
  {
    return;
  }

  this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);

  if (targetPtrIt->second == nullptr) // it's an external library
  {
    return;
  }

  std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;
  std::map<std::string, LinkLibraryScopeType> ll =
    getScopedLinkLibrariesFromTarget(targetPtrIt->second->Target);

  for (auto const& llit : ll) {
    const char* libName = llit.first.c_str();
    std::map<std::string, std::string>::const_iterator libNameIt =
      this->TargetNamesNodes.find(libName);

    // can happen e.g. if GRAPHVIZ_TARGET_IGNORE_REGEX is used
    if (libNameIt == this->TargetNamesNodes.end()) {
      continue;
    }

    std::string connectionName = myNodeName;
    connectionName += "-";
    connectionName += libNameIt->second;
    if (insertedConnections.find(connectionName) ==
        insertedConnections.end()) {
      insertedConnections.insert(connectionName);
      this->WriteNode(libName, this->TargetPtrs.find(libName)->second,
                      insertedNodes, str);

      str << "    \"" << myNodeName << "\" -> \"" << libNameIt->second << "\"";

      str << getLinkLibraryStyle(llit.second);

      str << " // " << targetName << " -> " << libName << std::endl;
      this->WriteConnections(libName, insertedNodes, insertedConnections, str);
    }
  }
}

void cmGraphVizWriter::WriteDependerConnections(
  const std::string& targetName, std::set<std::string>& insertedNodes,
  std::set<std::string>& insertedConnections, cmGeneratedFileStream& str) const
{
  std::map<std::string, const cmGeneratorTarget*>::const_iterator targetPtrIt =
    this->TargetPtrs.find(targetName);

  if (targetPtrIt == this->TargetPtrs.end()) // not found at all
  {
    return;
  }

  this->WriteNode(targetName, targetPtrIt->second, insertedNodes, str);

  if (targetPtrIt->second == nullptr) // it's an external library
  {
    return;
  }

  std::string myNodeName = this->TargetNamesNodes.find(targetName)->second;

  // now search who links against me
  for (auto const& tptr : this->TargetPtrs) {
    if (tptr.second == nullptr) {
      continue;
    }

    if (!this->GenerateForTargetType(tptr.second->GetType())) {
      continue;
    }

    // Now we have a target, check whether it links against targetName.
    // If so, draw a connection, and then continue with dependers on that one.
    std::map<std::string, LinkLibraryScopeType> ll =
      getScopedLinkLibrariesFromTarget(tptr.second->Target);

    for (auto const& llit : ll) {
      if (llit.first == targetName) {
        // So this target links against targetName.
        std::map<std::string, std::string>::const_iterator dependerNodeNameIt =
          this->TargetNamesNodes.find(tptr.first);

        if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
          std::string connectionName = dependerNodeNameIt->second;
          connectionName += "-";
          connectionName += myNodeName;

          if (insertedConnections.find(connectionName) ==
              insertedConnections.end()) {
            insertedConnections.insert(connectionName);
            this->WriteNode(tptr.first, tptr.second, insertedNodes, str);

            str << "    \"" << dependerNodeNameIt->second << "\" -> \""
                << myNodeName << "\"";
            str << " // " << targetName << " -> " << tptr.first << std::endl;
            str << getLinkLibraryStyle(llit.second);
            this->WriteDependerConnections(tptr.first, insertedNodes,
                                           insertedConnections, str);
          }
        }
        break;
      }
    }
  }
}

void cmGraphVizWriter::WriteNode(const std::string& targetName,
                                 const cmGeneratorTarget* target,
                                 std::set<std::string>& insertedNodes,
                                 cmGeneratedFileStream& str) const
{
  if (insertedNodes.find(targetName) == insertedNodes.end()) {
    insertedNodes.insert(targetName);
    std::map<std::string, std::string>::const_iterator nameIt =
      this->TargetNamesNodes.find(targetName);

    str << "    \"" << nameIt->second << "\" [ label=\"" << targetName
        << "\" shape=\"" << getShapeForTarget(target) << "\"];" << std::endl;
  }
}

void cmGraphVizWriter::CollectTargetsAndLibs()
{
  if (!this->HaveTargetsAndLibs) {
    this->HaveTargetsAndLibs = true;
    int cnt = this->CollectAllTargets();
    if (this->GenerateForExternals) {
      this->CollectAllExternalLibs(cnt);
    }
  }
}

int cmGraphVizWriter::CollectAllTargets()
{
  int cnt = 0;
  // First pass get the list of all cmake targets
  for (cmLocalGenerator* lg : this->LocalGenerators) {
    const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
    for (cmGeneratorTarget* target : targets) {
      const char* realTargetName = target->GetName().c_str();
      if (this->IgnoreThisTarget(realTargetName)) {
        // Skip ignored targets
        continue;
      }
      // std::cout << "Found target: " << tit->first << std::endl;
      std::ostringstream ostr;
      ostr << this->GraphNodePrefix << cnt++;
      this->TargetNamesNodes[realTargetName] = ostr.str();
      this->TargetPtrs[realTargetName] = target;
    }
  }

  return cnt;
}

int cmGraphVizWriter::CollectAllExternalLibs(int cnt)
{
  // Ok, now find all the stuff we link to that is not in cmake
  for (cmLocalGenerator* lg : this->LocalGenerators) {
    const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
    for (cmGeneratorTarget* target : targets) {
      const char* realTargetName = target->GetName().c_str();
      if (this->IgnoreThisTarget(realTargetName)) {
        // Skip ignored targets
        continue;
      }
      const cmTarget::LinkLibraryVectorType* ll =
        &(target->Target->GetOriginalLinkLibraries());
      for (auto const& llit : *ll) {
        const char* libName = llit.first.c_str();
        if (this->IgnoreThisTarget(libName)) {
          // Skip ignored targets
          continue;
        }

        std::map<std::string, const cmGeneratorTarget*>::const_iterator tarIt =
          this->TargetPtrs.find(libName);
        if (tarIt == this->TargetPtrs.end()) {
          std::ostringstream ostr;
          ostr << this->GraphNodePrefix << cnt++;
          this->TargetNamesNodes[libName] = ostr.str();
          this->TargetPtrs[libName] = nullptr;
          // str << "    \"" << ostr << "\" [ label=\"" << libName
          // <<  "\" shape=\"ellipse\"];" << std::endl;
        }
      }
    }
  }
  return cnt;
}

bool cmGraphVizWriter::IgnoreThisTarget(const std::string& name)
{
  for (cmsys::RegularExpression& regEx : this->TargetsToIgnoreRegex) {
    if (regEx.is_valid()) {
      if (regEx.find(name)) {
        return true;
      }
    }
  }

  return false;
}

bool cmGraphVizWriter::GenerateForTargetType(
  cmStateEnums::TargetType targetType) const
{
  switch (targetType) {
    case cmStateEnums::EXECUTABLE:
      return this->GenerateForExecutables;
    case cmStateEnums::STATIC_LIBRARY:
      return this->GenerateForStaticLibs;
    case cmStateEnums::SHARED_LIBRARY:
      return this->GenerateForSharedLibs;
    case cmStateEnums::MODULE_LIBRARY:
      return this->GenerateForModuleLibs;
    case cmStateEnums::INTERFACE_LIBRARY:
      return this->GenerateForInterface;
    default:
      break;
  }
  return false;
}
