/* 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 <cstddef>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <cmext/string_view>

#include "cmScanDepFormat.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmUnreachable.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)
{
  // 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.

  std::string mm;
  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 = cmStrCat(std::move(mm),
                    "-x c++-module\n"
                    "-fmodule-output=\"",
                    bmi_loc.Location(), "\"\n");
      break;
    }
  }

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

  return mm;
}

std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc,
                                   cmScanDepInfo const& obj)
{
  // 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.
  std::string mm = cmStrCat("$root ", loc.RootDirectory, '\n');

  for (auto const& p : obj.Provides) {
    auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName);
    if (bmi_loc.IsKnown()) {
      mm =
        cmStrCat(std::move(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 =
        cmStrCat(std::move(mm), r.LogicalName, ' ', bmi_loc.Location(), '\n');
    }
  }

  return mm;
}

std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc,
                                    cmScanDepInfo const& obj,
                                    CxxModuleUsage const& usages)
{
  // 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;
    }
    CM_UNREACHABLE;
    return ""_s;
  };

  std::string mm;
  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 =
        cmStrCat(std::move(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 = cmStrCat(std::move(mm), flag, " \"", usage.LogicalName, '=',
                  usage.Location, "\"\n");
  }

  return mm;
}
}

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

  CM_UNREACHABLE;
  return {};
}

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

  CM_UNREACHABLE;
  return CxxModuleMapMode::Default;
}
