/* 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 "cmState.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, const cmGlobalGenerator* globalGenerator)
{
  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 (globalGenerator->IsAlias(element)) {
      const auto tgt = globalGenerator->FindTarget(element);
      if (tgt) {
        element = tgt->GetName();
      }
    }

    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 (globalGenerator->IsAlias(element)) {
      const auto tgt = globalGenerator->FindTarget(element);
      if (tgt) {
        element = tgt->GetName();
      }
    }

    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 cmGlobalGenerator* globalGenerator)
  : GraphType("digraph")
  , GraphName("GG")
  , GraphHeader("node [\n  fontsize = \"12\"\n];")
  , GraphNodePrefix("node")
  , GlobalGenerator(globalGenerator)
  , LocalGenerators(globalGenerator->GetLocalGenerators())
  , GenerateForExecutables(true)
  , GenerateForStaticLibs(true)
  , GenerateForSharedLibs(true)
  , GenerateForModuleLibs(true)
  , GenerateForInterface(true)
  , GenerateForExternals(true)
  , GeneratePerTarget(true)
  , GenerateDependers(true)
  , HaveTargetsAndLibs(false)
{
}

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

  std::string 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)                                    \
  do {                                                                        \
    const char* value = mf.GetDefinition(cmakeDefinition);                    \
    if (value) {                                                              \
      (var) = value;                                                          \
    }                                                                         \
  } while (false)

  __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)                               \
  do {                                                                        \
    const char* value = mf.GetDefinition(cmakeDefinition);                    \
    if (value) {                                                              \
      (var) = mf.IsOn(cmakeDefinition);                                       \
    }                                                                         \
  } while (false)

  __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 std::string& 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);
    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 std::string& 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);
    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 std::string& 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,
                                     GlobalGenerator);

  for (auto const& llit : ll) {
    const std::string& libName = llit.first;
    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, GlobalGenerator);

    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 std::string& realTargetName = target->GetName();
      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 std::string& realTargetName = target->GetName();
      if (this->IgnoreThisTarget(realTargetName)) {
        // Skip ignored targets
        continue;
      }
      const cmTarget::LinkLibraryVectorType* ll =
        &(target->Target->GetOriginalLinkLibraries());
      for (auto const& llit : *ll) {
        std::string libName = llit.first;
        if (this->IgnoreThisTarget(libName)) {
          // Skip ignored targets
          continue;
        }

        if (GlobalGenerator->IsAlias(libName)) {
          const auto tgt = GlobalGenerator->FindTarget(libName);
          if (tgt) {
            libName = tgt->GetName();
          }
        }

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