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

#include "cmConfigure.h" // IWYU pragma: keep

#include <functional>
#include <string>
#include <utility>
#include <vector>

#include <cm/optional>
#include <cmext/algorithm>

#include "cmDiagnosticContext.h"
#include "cmDiagnostics.h"
#include "cmExportFileGenerator.h"
#include "cmStateTypes.h"

class cmExportSet;
class cmGeneratorTarget;
class cmLocalGenerator;
class cmMakefile;

/** \class cmExportBuildCMakeConfigGenerator
 * \brief Generate a file exporting targets from a build tree.
 *
 * cmExportBuildCMakeConfigGenerator is the interface class for generating a
 * file exporting targets from a build tree.
 *
 * This is used to implement the export() command.
 */
class cmExportBuildFileGenerator : virtual public cmExportFileGenerator
{
public:
  struct TargetExport
  {
    TargetExport(std::string name, std::string xcFrameworkLocation)
      : Name(std::move(name))
      , XcFrameworkLocation(std::move(xcFrameworkLocation))
    {
    }

    std::string Name;
    std::string XcFrameworkLocation;
  };

  cmExportBuildFileGenerator(cmDiagnosticContext context);

  /** Set the list of targets to export.  */
  void SetTargets(std::vector<TargetExport> const& targets)
  {
    this->Targets = targets;
  }
  void GetTargets(std::vector<TargetExport>& targets) const;
  void AppendTargets(std::vector<TargetExport> const& targets)
  {
    cm::append(this->Targets, targets);
  }
  void SetExportSet(cmExportSet*);

  struct ExportRecord
  {
    std::string Name;      // export set name; empty for anonymous exports
    std::string Namespace; // export namespace
  };

  /** If this export contains `target`, return a record identifying it
   *  (export set name + namespace).  Used by cmGlobalGenerator to assemble
   *  a project-wide view of where targets are exported.  */
  cm::optional<ExportRecord> FindRecordForTarget(
    cmGeneratorTarget const* target) const;

  /** Set the name of the C++ module directory.  */
  void SetCxxModuleDirectory(std::string cxx_module_dir)
  {
    this->CxxModulesDirectory = std::move(cxx_module_dir);
  }
  std::string const& GetCxxModuleDirectory() const
  {
    return this->CxxModulesDirectory;
  }

  void Compute(cmLocalGenerator* lg);

  /** Capture context for generator.  */
  static cmDiagnosticContext CaptureContext(cmMakefile const& mf);

protected:
  cmStateEnums::TargetType GetExportTargetType(
    cmGeneratorTarget const* target) const;

  /** Walk the list of targets to be exported.  Returns true iff no duplicates
      are found.  */
  bool CollectExports(std::function<void(cmGeneratorTarget const*)> visitor);

  void HandleMissingTarget(std::string& link_libs,
                           cmGeneratorTarget const* depender,
                           cmGeneratorTarget* dependee) override;

  void ComplainAboutMissingTarget(cmGeneratorTarget const* depender,
                                  cmGeneratorTarget const* dependee,
                                  ExportInfo const& exportInfo) const;

  void ComplainAboutDuplicateTarget(
    std::string const& targetName) const override;

  void IssueMessage(MessageType type,
                    std::string const& message) const override;
  void IssueDiagnostic(cmDiagnosticCategory category,
                       std::string const& message) const override;

  /** Fill in properties indicating built file locations.  */
  void SetImportLocationProperty(std::string const& config,
                                 std::string const& suffix,
                                 cmGeneratorTarget* target,
                                 ImportPropertyMap& properties);

  std::string InstallNameDir(cmGeneratorTarget const* target,
                             std::string const& config) override;

  cmExportSet* GetExportSet() const override { return this->ExportSet; }

  std::string GetCxxModulesDirectory() const override
  {
    return this->CxxModulesDirectory;
  }

  ExportInfo FindExportInfo(cmGeneratorTarget const* target) const override;

  using cmExportFileGenerator::PopulateInterfaceProperties;
  bool PopulateInterfaceProperties(cmGeneratorTarget const* target,
                                   ImportPropertyMap& properties);

  using cmExportFileGenerator::PopulateFileSetInterfaceProperties;
  bool PopulateFileSetInterfaceProperties(
    cmGeneratorTarget const* target, ImportFileSetPropertyMap& properties);

  struct TargetExportPrivate
  {
    TargetExportPrivate(cmGeneratorTarget* target,
                        std::string xcFrameworkLocation)
      : Target(target)
      , XcFrameworkLocation(std::move(xcFrameworkLocation))
    {
    }

    cmGeneratorTarget* Target;
    std::string XcFrameworkLocation;
  };

  cmDiagnosticContext Context;
  std::vector<TargetExport> Targets;
  cmExportSet* ExportSet;
  std::vector<TargetExportPrivate> Exports;
  cmLocalGenerator* LG;
  // The directory for C++ module information.
  std::string CxxModulesDirectory;
};
