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

#include <map>
#include <utility>
#include <vector>

#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmMakefile.h"

void cmLinkItemGraphVisitor::VisitItem(cmLinkItem const& item)
{
  if (this->ItemVisited(item)) {
    return;
  }

  this->OnItem(item);

  this->VisitLinks(item, item);
}

void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
                                        cmLinkItem const& rootItem)
{
  if (this->LinkVisited(item, rootItem)) {
    return;
  }

  if (item.Target == nullptr) {
    return;
  }

  for (auto const& config : item.Target->Makefile->GetGeneratorConfigs()) {
    this->VisitLinks(item, rootItem, config);
  }
}

void cmLinkItemGraphVisitor::VisitLinks(cmLinkItem const& item,
                                        cmLinkItem const& rootItem,
                                        std::string const& config)
{
  auto const& target = *item.Target;

  DependencyMap dependencies;
  cmLinkItemGraphVisitor::GetDependencies(target, config, dependencies);

  for (auto const& d : dependencies) {
    auto const& dependency = d.second;
    auto const& dependencyType = dependency.first;
    auto const& dependee = dependency.second;
    this->VisitItem(dependee);

    if (this->LinkVisited(item, dependee)) {
      continue;
    }

    this->OnDirectLink(item, dependee, dependencyType);

    if (rootItem.AsStr() != item.AsStr()) {
      this->OnIndirectLink(rootItem, dependee);
    }

    // Visit all the direct and indirect links.
    this->VisitLinks(dependee, dependee);
    this->VisitLinks(dependee, item);
    this->VisitLinks(dependee, rootItem);
  }
}

bool cmLinkItemGraphVisitor::ItemVisited(cmLinkItem const& item)
{
  auto& collection = this->VisitedItems;

  bool const visited = collection.find(item.AsStr()) != collection.cend();

  if (!visited) {
    collection.insert(item.AsStr());
  }

  return visited;
}

bool cmLinkItemGraphVisitor::LinkVisited(cmLinkItem const& depender,
                                         cmLinkItem const& dependee)
{
  auto const link = std::make_pair<>(depender.AsStr(), dependee.AsStr());

  bool const linkVisited =
    this->VisitedLinks.find(link) != this->VisitedLinks.cend();

  if (!linkVisited) {
    this->VisitedLinks.insert(link);
  }

  return linkVisited;
}

void cmLinkItemGraphVisitor::GetDependencies(cmGeneratorTarget const& target,
                                             std::string const& config,
                                             DependencyMap& dependencies)
{
  auto implementationLibraries = target.GetLinkImplementationLibraries(config);
  if (implementationLibraries != nullptr) {
    for (auto const& lib : implementationLibraries->Libraries) {
      auto const& name = lib.AsStr();
      dependencies[name] = Dependency(DependencyType::LinkPrivate, lib);
    }
  }

  auto interfaceLibraries =
    target.GetLinkInterfaceLibraries(config, &target, true);
  if (interfaceLibraries != nullptr) {
    for (auto const& lib : interfaceLibraries->Libraries) {
      auto const& name = lib.AsStr();
      if (dependencies.find(name) != dependencies.cend()) {
        dependencies[name] = Dependency(DependencyType::LinkPublic, lib);
      } else {
        dependencies[name] = Dependency(DependencyType::LinkInterface, lib);
      }
    }
  }

  std::vector<cmGeneratorTarget*> objectLibraries;
  target.GetObjectLibrariesCMP0026(objectLibraries);
  for (auto const& lib : objectLibraries) {
    auto const& name = lib->GetName();
    if (dependencies.find(name) == dependencies.cend()) {
      auto objectItem = cmLinkItem(lib, false, lib->GetBacktrace());
      dependencies[name] = Dependency(DependencyType::Object, objectItem);
    }
  }

  auto const& utilityItems = target.GetUtilityItems();
  for (auto const& item : utilityItems) {
    auto const& name = item.AsStr();
    if (dependencies.find(name) == dependencies.cend()) {
      dependencies[name] = Dependency(DependencyType::Utility, item);
    }
  }
}
