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

#include <algorithm>
#include <memory>
#include <utility>

#include <cmext/algorithm>

#include <cmsys/Glob.hxx>

#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmValue.h"
#include "cmake.h"

cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm)
  : cmGlobalGenerator(cm)
{
}

cmGlobalCommonGenerator::~cmGlobalCommonGenerator() = default;

std::map<std::string, cmGlobalCommonGenerator::DirectoryTarget>
cmGlobalCommonGenerator::ComputeDirectoryTargets() const
{
  std::map<std::string, DirectoryTarget> dirTargets;
  for (auto const& lg : this->LocalGenerators) {
    std::string currentBinaryDir =
      lg->GetStateSnapshot().GetDirectory().GetCurrentBinary();
    DirectoryTarget& dirTarget = dirTargets[currentBinaryDir];
    dirTarget.LG = lg.get();
    std::vector<std::string> const& configs =
      static_cast<cmLocalCommonGenerator const*>(lg.get())->GetConfigNames();

    // The directory-level rule should depend on the target-level rules
    // for all targets in the directory.
    for (auto const& gt : lg->GetGeneratorTargets()) {
      cmStateEnums::TargetType const type = gt->GetType();
      if (type == cmStateEnums::GLOBAL_TARGET || !gt->IsInBuildSystem()) {
        continue;
      }
      DirectoryTarget::Target t;
      t.GT = gt.get();
      std::string const EXCLUDE_FROM_ALL("EXCLUDE_FROM_ALL");
      if (cmValue exclude = gt->GetProperty(EXCLUDE_FROM_ALL)) {
        for (std::string const& config : configs) {
          cmGeneratorExpressionInterpreter genexInterpreter(lg.get(), config,
                                                            gt.get());
          if (cmIsOn(genexInterpreter.Evaluate(*exclude, EXCLUDE_FROM_ALL))) {
            // This target has been explicitly excluded.
            t.ExcludedFromAllInConfigs.push_back(config);
          }
        }

        if (t.ExcludedFromAllInConfigs.empty()) {
          // This target has been explicitly un-excluded.  The directory-level
          // rule for every directory between this and the root should depend
          // on the target-level rule for this target.
          for (cmStateSnapshot dir =
                 lg->GetStateSnapshot().GetBuildsystemDirectoryParent();
               dir.IsValid(); dir = dir.GetBuildsystemDirectoryParent()) {
            std::string d = dir.GetDirectory().GetCurrentBinary();
            dirTargets[d].Targets.emplace_back(t);
          }
        }
      }
      dirTarget.Targets.emplace_back(t);
    }

    // The directory-level rule should depend on the directory-level
    // rules of the subdirectories.
    for (cmStateSnapshot const& state : lg->GetStateSnapshot().GetChildren()) {
      DirectoryTarget::Dir d;
      d.Path = state.GetDirectory().GetCurrentBinary();
      d.ExcludeFromAll =
        state.GetDirectory().GetPropertyAsBool("EXCLUDE_FROM_ALL");
      dirTarget.Children.emplace_back(std::move(d));
    }
  }

  return dirTargets;
}

bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig(
  DirectoryTarget::Target const& t, std::string const& config)
{
  if (this->IsMultiConfig()) {
    return cm::contains(t.ExcludedFromAllInConfigs, config);
  }
  return !t.ExcludedFromAllInConfigs.empty();
}

std::string cmGlobalCommonGenerator::GetEditCacheCommand() const
{
  // If generating for an extra IDE, the edit_cache target cannot
  // launch a terminal-interactive tool, so always use cmake-gui.
  if (!this->GetExtraGeneratorName().empty()) {
    return cmSystemTools::GetCMakeGUICommand();
  }

  // Use an internal cache entry to track the latest dialog used
  // to edit the cache, and use that for the edit_cache target.
  cmake* cm = this->GetCMakeInstance();
  std::string editCacheCommand = cm->GetCMakeEditCommand();
  if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") ||
      !editCacheCommand.empty()) {
    if (this->SupportsDirectConsole() && editCacheCommand.empty()) {
      editCacheCommand = cmSystemTools::GetCMakeCursesCommand();
    }
    if (editCacheCommand.empty()) {
      editCacheCommand = cmSystemTools::GetCMakeGUICommand();
    }
    if (!editCacheCommand.empty()) {
      cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand,
                        "Path to cache edit program executable.",
                        cmStateEnums::INTERNAL);
    }
  }
  cmValue edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND");
  return edit_cmd ? *edit_cmd : std::string();
}

void cmGlobalCommonGenerator::RemoveUnknownClangTidyExportFixesFiles() const
{
  for (auto const& dir : this->ClangTidyExportFixesDirs) {
    cmsys::Glob g;
    g.SetRecurse(true);
    g.SetListDirs(false);
    g.FindFiles(cmStrCat(dir, "/*.yaml"));
    for (auto const& file : g.GetFiles()) {
      if (!this->ClangTidyExportFixesFiles.count(file) &&
          !std::any_of(this->ClangTidyExportFixesFiles.begin(),
                       this->ClangTidyExportFixesFiles.end(),
                       [&file](std::string const& knownFile) -> bool {
                         return cmSystemTools::SameFile(file, knownFile);
                       })) {
        cmSystemTools::RemoveFile(file);
      }
    }
  }
}
