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

#include <cassert>
#include <cstddef>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <cm/string_view>
#include <cmext/string_view>

#include "cmScanDepFormat.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

CxxBmiLocation::CxxBmiLocation() = default;

CxxBmiLocation::CxxBmiLocation(std::string path)
  : BmiLocation(std::move(path))
{
}

CxxBmiLocation CxxBmiLocation::Unknown()
{
  return {};
}

CxxBmiLocation CxxBmiLocation::Private()
{
  return { std::string{} };
}

CxxBmiLocation CxxBmiLocation::Known(std::string path)
{
  return { std::move(path) };
}

bool CxxBmiLocation::IsKnown() const
{
  return this->BmiLocation.has_value();
}

bool CxxBmiLocation::IsPrivate() const
{
  if (auto const& loc = this->BmiLocation) {
    return loc->empty();
  }
  return false;
}

std::string const& CxxBmiLocation::Location() const
{
  if (auto const& loc = this->BmiLocation) {
    return *loc;
  }
  static std::string empty;
  return empty;
}

CxxBmiLocation CxxModuleLocations::BmiGeneratorPathForModule(
  std::string const& logical_name) const
{
  auto bmi_loc = this->BmiLocationForModule(logical_name);
  if (bmi_loc.IsKnown() && !bmi_loc.IsPrivate()) {
    bmi_loc =
      CxxBmiLocation::Known(this->PathForGenerator(bmi_loc.Location()));
  }
  return bmi_loc;
}

namespace {

struct TransitiveUsage
{
  TransitiveUsage(std::string name, std::string location, LookupMethod method)
    : LogicalName(std::move(name))
    , Location(std::move(location))
    , Method(method)
  {
  }

  std::string LogicalName;
  std::string Location;
  LookupMethod Method;
};

std::vector<TransitiveUsage> GetTransitiveUsages(
  CxxModuleLocations const& loc, std::vector<cmSourceReqInfo> const& required,
  CxxModuleUsage const& usages)
{
  std::set<std::string> transitive_usage_directs;
  std::set<std::string> transitive_usage_names;

  std::vector<TransitiveUsage> all_usages;

  for (auto const& r : required) {
    auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName);
    if (bmi_loc.IsKnown()) {
      all_usages.emplace_back(r.LogicalName, bmi_loc.Location(), r.Method);
      transitive_usage_directs.insert(r.LogicalName);

      // Insert transitive usages.
      auto transitive_usages = usages.Usage.find(r.LogicalName);
      if (transitive_usages != usages.Usage.end()) {
        transitive_usage_names.insert(transitive_usages->second.begin(),
                                      transitive_usages->second.end());
      }
    }
  }

  for (auto const& transitive_name : transitive_usage_names) {
    if (transitive_usage_directs.count(transitive_name)) {
      continue;
    }

    auto module_ref = usages.Reference.find(transitive_name);
    if (module_ref != usages.Reference.end()) {
      all_usages.emplace_back(transitive_name, module_ref->second.Path,
                              module_ref->second.Method);
    }
  }

  return all_usages;
}

std::string CxxModuleMapContentClang(CxxModuleLocations const& loc,
                                     cmScanDepInfo const& obj,
                                     CxxModuleUsage const& usages)
{
  std::stringstream mm;

  // Clang's command line only supports a single output. If more than one is
  // expected, we cannot make a useful module map file.
  if (obj.Provides.size() > 1) {
    return {};
  }

  // A series of flags which tell the compiler where to look for modules.

  for (auto const& p : obj.Provides) {
    auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName);
    if (bmi_loc.IsKnown()) {
      // Force the TU to be considered a C++ module source file regardless of
      // extension.
      mm << "-x c++-module\n";

      mm << "-fmodule-output=" << bmi_loc.Location() << '\n';
      break;
    }
  }

  auto all_usages = GetTransitiveUsages(loc, obj.Requires, usages);
  for (auto const& usage : all_usages) {
    mm << "-fmodule-file=" << usage.LogicalName << '=' << usage.Location
       << '\n';
  }

  return mm.str();
}

std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc,
                                   cmScanDepInfo const& obj)
{
  std::stringstream mm;

  // Documented in GCC's documentation. The format is a series of
  // lines with a module name and the associated filename separated
  // by spaces. The first line may use `$root` as the module name
  // to specify a "repository root". That is used to anchor any
  // relative paths present in the file (CMake should never
  // generate any).

  // Write the root directory to use for module paths.
  mm << "$root " << loc.RootDirectory << '\n';

  for (auto const& p : obj.Provides) {
    auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName);
    if (bmi_loc.IsKnown()) {
      mm << p.LogicalName << ' ' << bmi_loc.Location() << '\n';
    }
  }
  for (auto const& r : obj.Requires) {
    auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName);
    if (bmi_loc.IsKnown()) {
      mm << r.LogicalName << ' ' << bmi_loc.Location() << '\n';
    }
  }

  return mm.str();
}

std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc,
                                    cmScanDepInfo const& obj,
                                    CxxModuleUsage const& usages)
{
  std::stringstream mm;

  // A response file of `-reference NAME=PATH` arguments.

  // MSVC's command line only supports a single output. If more than one is
  // expected, we cannot make a useful module map file.
  if (obj.Provides.size() > 1) {
    return {};
  }

  auto flag_for_method = [](LookupMethod method) -> cm::static_string_view {
    switch (method) {
      case LookupMethod::ByName:
        return "-reference"_s;
      case LookupMethod::IncludeAngle:
        return "-headerUnit:angle"_s;
      case LookupMethod::IncludeQuote:
        return "-headerUnit:quote"_s;
    }
    assert(false && "unsupported lookup method");
    return ""_s;
  };

  for (auto const& p : obj.Provides) {
    if (p.IsInterface) {
      mm << "-interface\n";
    } else {
      mm << "-internalPartition\n";
    }

    auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName);
    if (bmi_loc.IsKnown()) {
      mm << "-ifcOutput " << bmi_loc.Location() << '\n';
    }
  }

  auto all_usages = GetTransitiveUsages(loc, obj.Requires, usages);
  for (auto const& usage : all_usages) {
    auto flag = flag_for_method(usage.Method);

    mm << flag << ' ' << usage.LogicalName << '=' << usage.Location << '\n';
  }

  return mm.str();
}
}

bool CxxModuleUsage::AddReference(std::string const& logical,
                                  std::string const& loc, LookupMethod method)
{
  auto r = this->Reference.find(logical);
  if (r != this->Reference.end()) {
    auto& ref = r->second;

    if (ref.Path == loc && ref.Method == method) {
      return true;
    }

    auto method_name = [](LookupMethod m) -> cm::static_string_view {
      switch (m) {
        case LookupMethod::ByName:
          return "by-name"_s;
        case LookupMethod::IncludeAngle:
          return "include-angle"_s;
        case LookupMethod::IncludeQuote:
          return "include-quote"_s;
      }
      assert(false && "unsupported lookup method");
      return ""_s;
    };

    cmSystemTools::Error(cmStrCat("Disagreement of the location of the '",
                                  logical,
                                  "' module. "
                                  "Location A: '",
                                  ref.Path, "' via ", method_name(ref.Method),
                                  "; "
                                  "Location B: '",
                                  loc, "' via ", method_name(method), "."));
    return false;
  }

  auto& ref = this->Reference[logical];
  ref.Path = loc;
  ref.Method = method;

  return true;
}

cm::static_string_view CxxModuleMapExtension(
  cm::optional<CxxModuleMapFormat> format)
{
  if (format) {
    switch (*format) {
      case CxxModuleMapFormat::Clang:
        return ".pcm"_s;
      case CxxModuleMapFormat::Gcc:
        return ".gcm"_s;
      case CxxModuleMapFormat::Msvc:
        return ".ifc"_s;
    }
  }

  return ".bmi"_s;
}

std::set<std::string> CxxModuleUsageSeed(
  CxxModuleLocations const& loc, std::vector<cmScanDepInfo> const& objects,
  CxxModuleUsage& usages, bool& private_usage_found)
{
  // Track inner usages to populate usages from internal bits.
  //
  // This is a map of modules that required some other module that was not
  // found to those that were not found.
  std::map<std::string, std::set<std::string>> internal_usages;
  std::set<std::string> unresolved;

  for (cmScanDepInfo const& object : objects) {
    // Add references for each of the provided modules.
    for (auto const& p : object.Provides) {
      auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName);
      if (bmi_loc.IsKnown()) {
        // XXX(cxx-modules): How to support header units?
        usages.AddReference(p.LogicalName, bmi_loc.Location(),
                            LookupMethod::ByName);
      }
    }

    // For each requires, pull in what is required.
    for (auto const& r : object.Requires) {
      // Find the required name in the current target.
      auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName);
      if (bmi_loc.IsPrivate()) {
        cmSystemTools::Error(
          cmStrCat("Unable to use module '", r.LogicalName,
                   "' as it is 'PRIVATE' and therefore not accessible outside "
                   "of its owning target."));
        private_usage_found = true;
        continue;
      }

      // Find transitive usages.
      auto transitive_usages = usages.Usage.find(r.LogicalName);

      for (auto const& p : object.Provides) {
        auto& this_usages = usages.Usage[p.LogicalName];

        // Add the direct usage.
        this_usages.insert(r.LogicalName);

        if (transitive_usages == usages.Usage.end() ||
            internal_usages.find(r.LogicalName) != internal_usages.end()) {
          // Mark that we need to update transitive usages later.
          if (bmi_loc.IsKnown()) {
            internal_usages[p.LogicalName].insert(r.LogicalName);
          }
        } else {
          // Add the transitive usage.
          this_usages.insert(transitive_usages->second.begin(),
                             transitive_usages->second.end());
        }
      }

      if (bmi_loc.IsKnown()) {
        usages.AddReference(r.LogicalName, bmi_loc.Location(), r.Method);
      }
    }
  }

  // While we have internal usages to manage.
  while (!internal_usages.empty()) {
    size_t starting_size = internal_usages.size();

    // For each internal usage.
    for (auto usage = internal_usages.begin(); usage != internal_usages.end();
         /* see end of loop */) {
      auto& this_usages = usages.Usage[usage->first];

      for (auto use = usage->second.begin(); use != usage->second.end();
           /* see end of loop */) {
        // Check if this required module uses other internal modules; defer
        // if so.
        if (internal_usages.count(*use)) {
          // Advance the iterator.
          ++use;
          continue;
        }

        auto transitive_usages = usages.Usage.find(*use);
        if (transitive_usages != usages.Usage.end()) {
          this_usages.insert(transitive_usages->second.begin(),
                             transitive_usages->second.end());
        }

        // Remove the entry and advance the iterator.
        use = usage->second.erase(use);
      }

      // Erase the entry if it doesn't have any remaining usages.
      if (usage->second.empty()) {
        usage = internal_usages.erase(usage);
      } else {
        ++usage;
      }
    }

    // Check that at least one usage was resolved.
    if (starting_size == internal_usages.size()) {
      // Nothing could be resolved this loop; we have a cycle, so record the
      // cycle and exit.
      for (auto const& usage : internal_usages) {
        unresolved.insert(usage.first);
      }
      break;
    }
  }

  return unresolved;
}

std::string CxxModuleMapContent(CxxModuleMapFormat format,
                                CxxModuleLocations const& loc,
                                cmScanDepInfo const& obj,
                                CxxModuleUsage const& usages)
{
  switch (format) {
    case CxxModuleMapFormat::Clang:
      return CxxModuleMapContentClang(loc, obj, usages);
    case CxxModuleMapFormat::Gcc:
      return CxxModuleMapContentGcc(loc, obj);
    case CxxModuleMapFormat::Msvc:
      return CxxModuleMapContentMsvc(loc, obj, usages);
  }

  assert(false);
  return {};
}

CxxModuleMapMode CxxModuleMapOpenMode(CxxModuleMapFormat format)
{
  switch (format) {
    case CxxModuleMapFormat::Gcc:
      return CxxModuleMapMode::Binary;
    case CxxModuleMapFormat::Clang:
    case CxxModuleMapFormat::Msvc:
      return CxxModuleMapMode::Default;
  }

  assert(false);
  return CxxModuleMapMode::Default;
}
