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

#include <cstddef>
#include <functional>

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

#include "cmExecutionStatus.h"
#include "cmFileSet.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmPropertyDefinition.h"
#include "cmSetPropertyCommand.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmValue.h"
#include "cmake.h"

namespace {
enum OutType
{
  OutValue,
  OutDefined,
  OutBriefDoc,
  OutFullDoc,
  OutSet
};

// Implementation of each property type.
bool HandleGlobalMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName);
bool HandleDirectoryMode(cmExecutionStatus& status, std::string const& name,
                         OutType infoType, std::string const& variable,
                         std::string const& propertyName);
bool HandleTargetMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName);
bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
                       OutType infoType, std::string const& variable,
                       std::string const& propertyName, cmTarget* target);
bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName,
                      cmMakefile& directory_makefile,
                      bool source_file_paths_should_be_absolute);
bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
                    OutType infoType, std::string const& variable,
                    std::string const& propertyName,
                    cmMakefile& directory_makefile);
bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
                        OutType infoType, std::string const& variable,
                        std::string const& propertyName);
bool HandleCacheMode(cmExecutionStatus& status, std::string const& name,
                     OutType infoType, std::string const& variable,
                     std::string const& propertyName);
bool HandleInstallMode(cmExecutionStatus& status, std::string const& name,
                       OutType infoType, std::string const& variable,
                       std::string const& propertyName);
}

bool cmGetPropertyCommand(std::vector<std::string> const& args,
                          cmExecutionStatus& status)
{
  OutType infoType = OutValue;
  if (args.size() < 3) {
    status.SetError("called with incorrect number of arguments");
    return false;
  }

  // The cmake variable in which to store the result.
  std::string const& variable = args[0];

  std::string name;
  std::string propertyName;

  std::string file_set_target_name;
  bool file_set_target_option_enabled = false;

  std::vector<std::string> source_file_directories;
  std::vector<std::string> source_file_target_directories;
  bool source_file_directory_option_enabled = false;
  bool source_file_target_option_enabled = false;

  std::string test_directory;
  bool test_directory_option_enabled = false;

  // Get the scope from which to get the property.
  cmProperty::ScopeType scope;
  if (args[1] == "GLOBAL") {
    scope = cmProperty::GLOBAL;
  } else if (args[1] == "DIRECTORY") {
    scope = cmProperty::DIRECTORY;
  } else if (args[1] == "TARGET") {
    scope = cmProperty::TARGET;
  } else if (args[1] == "FILE_SET") {
    scope = cmProperty::FILE_SET;
  } else if (args[1] == "SOURCE") {
    scope = cmProperty::SOURCE_FILE;
  } else if (args[1] == "TEST") {
    scope = cmProperty::TEST;
  } else if (args[1] == "VARIABLE") {
    scope = cmProperty::VARIABLE;
  } else if (args[1] == "CACHE") {
    scope = cmProperty::CACHE;
  } else if (args[1] == "INSTALL") {
    scope = cmProperty::INSTALL;
  } else {
    status.SetError(cmStrCat("given invalid scope ", args[1],
                             ".  "
                             "Valid scopes are "
                             "GLOBAL, DIRECTORY, TARGET, FILE_SET, SOURCE, "
                             "TEST, VARIABLE, CACHE, INSTALL."));
    return false;
  }

  // Parse remaining arguments.
  enum Doing
  {
    DoingNone,
    DoingName,
    DoingProperty,
    DoingType,
    DoingFileSetTarget,
    DoingSourceDirectory,
    DoingSourceTargetDirectory,
    DoingTestDirectory,
  };
  Doing doing = DoingName;
  for (unsigned int i = 2; i < args.size(); ++i) {
    if (args[i] == "PROPERTY") {
      doing = DoingProperty;
    } else if (args[i] == "BRIEF_DOCS") {
      doing = DoingNone;
      infoType = OutBriefDoc;
    } else if (args[i] == "FULL_DOCS") {
      doing = DoingNone;
      infoType = OutFullDoc;
    } else if (args[i] == "SET") {
      doing = DoingNone;
      infoType = OutSet;
    } else if (args[i] == "DEFINED") {
      doing = DoingNone;
      infoType = OutDefined;
    } else if (doing == DoingName) {
      doing = DoingNone;
      name = args[i];
    } else if (doing == DoingNone && scope == cmProperty::FILE_SET &&
               args[i] == "TARGET") {
      doing = DoingFileSetTarget;
      file_set_target_option_enabled = true;
    } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
               args[i] == "DIRECTORY") {
      doing = DoingSourceDirectory;
      source_file_directory_option_enabled = true;
    } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE &&
               args[i] == "TARGET_DIRECTORY") {
      doing = DoingSourceTargetDirectory;
      source_file_target_option_enabled = true;
    } else if (doing == DoingNone && scope == cmProperty::TEST &&
               args[i] == "DIRECTORY") {
      doing = DoingTestDirectory;
      test_directory_option_enabled = true;
    } else if (doing == DoingFileSetTarget) {
      file_set_target_name = args[i];
      doing = DoingNone;
    } else if (doing == DoingSourceDirectory) {
      source_file_directories.push_back(args[i]);
      doing = DoingNone;
    } else if (doing == DoingSourceTargetDirectory) {
      source_file_target_directories.push_back(args[i]);
      doing = DoingNone;
    } else if (doing == DoingTestDirectory) {
      test_directory = args[i];
      doing = DoingNone;
    } else if (doing == DoingProperty) {
      doing = DoingNone;
      propertyName = args[i];
    } else {
      status.SetError(cmStrCat("given invalid argument \"", args[i], "\"."));
      return false;
    }
  }

  // Make sure a property name was found.
  if (propertyName.empty()) {
    status.SetError("not given a PROPERTY <name> argument.");
    return false;
  }

  // Compute requested output.
  if (infoType == OutBriefDoc) {
    // Lookup brief documentation.
    std::string output;
    if (cmPropertyDefinition const* def =
          status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
                                                                 scope)) {
      output = def->GetShortDescription();
    }
    if (output.empty()) {
      output = "NOTFOUND";
    }
    status.GetMakefile().AddDefinition(variable, output);
  } else if (infoType == OutFullDoc) {
    // Lookup full documentation.
    std::string output;
    if (cmPropertyDefinition const* def =
          status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
                                                                 scope)) {
      output = def->GetFullDescription();
    }
    if (output.empty()) {
      output = "NOTFOUND";
    }
    status.GetMakefile().AddDefinition(variable, output);
  } else if (infoType == OutDefined) {
    // Lookup if the property is defined
    if (status.GetMakefile().GetState()->GetPropertyDefinition(propertyName,
                                                               scope)) {
      status.GetMakefile().AddDefinition(variable, "1");
    } else {
      status.GetMakefile().AddDefinition(variable, "0");
    }
  } else {
    // Dispatch property getting.
    switch (scope) {
      case cmProperty::GLOBAL:
        return HandleGlobalMode(status, name, infoType, variable,
                                propertyName);
      case cmProperty::DIRECTORY:
        return HandleDirectoryMode(status, name, infoType, variable,
                                   propertyName);
      case cmProperty::TARGET:
        return HandleTargetMode(status, name, infoType, variable,
                                propertyName);
      case cmProperty::FILE_SET: {
        cmTarget* file_set_target;
        if (!SetPropertyCommand::HandleAndValidateFileSetTargetScopes(
              status, file_set_target_option_enabled, file_set_target_name,
              file_set_target)) {
          return false;
        }
        return HandleFileSetMode(status, name, infoType, variable,
                                 propertyName, file_set_target);
      }
      case cmProperty::SOURCE_FILE: {
        std::vector<cmMakefile*> source_file_directory_makefiles;
        if (!SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
              status, source_file_directory_option_enabled,
              source_file_target_option_enabled, source_file_directories,
              source_file_target_directories,
              source_file_directory_makefiles)) {
          return false;
        }
        bool source_file_paths_should_be_absolute =
          source_file_directory_option_enabled ||
          source_file_target_option_enabled;
        cmMakefile& directory_scope_mf = *(source_file_directory_makefiles[0]);
        return HandleSourceMode(status, name, infoType, variable, propertyName,
                                directory_scope_mf,
                                source_file_paths_should_be_absolute);
      }
      case cmProperty::TEST: {
        cmMakefile* test_directory_makefile;
        if (!SetPropertyCommand::HandleAndValidateTestDirectoryScopes(
              status, test_directory_option_enabled, test_directory,
              test_directory_makefile)) {
          return false;
        }
        return HandleTestMode(status, name, infoType, variable, propertyName,
                              *test_directory_makefile);
      }
      case cmProperty::VARIABLE:
        return HandleVariableMode(status, name, infoType, variable,
                                  propertyName);
      case cmProperty::CACHE:
        return HandleCacheMode(status, name, infoType, variable, propertyName);
      case cmProperty::INSTALL:
        return HandleInstallMode(status, name, infoType, variable,
                                 propertyName);

      case cmProperty::CACHED_VARIABLE:
        break; // should never happen
    }
  }

  return true;
}

namespace GetPropertyCommand {
bool GetSourceFilePropertyGENERATED(
  std::string const& name, cmMakefile& mf,
  std::function<bool(bool)> const& storeResult)
{
  // Globally set as generated?
  // Note: If the given "name" only contains a filename or a relative path
  //       the file's location is ambiguous. In general, one would expect
  //       it in the source-directory, because that is where source files
  //       are located normally. However, generated files are normally
  //       generated in the build-directory. Therefore, we first check for
  //       a generated file in the build-directory before we check for a
  //       generated file in the source-directory.
  {
    auto file =
      cmSystemTools::CollapseFullPath(name, mf.GetCurrentBinaryDirectory());
    if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
      return storeResult(true);
    }
  }
  {
    auto file =
      cmSystemTools::CollapseFullPath(name, mf.GetCurrentSourceDirectory());
    if (mf.GetGlobalGenerator()->IsGeneratedFile(file)) {
      return storeResult(true);
    }
  }
  // Skip checking the traditional/local property.
  return storeResult(false);
}
}

namespace {

// Implementation of result storage.
template <typename ValueType>
bool StoreResult(OutType infoType, cmMakefile& makefile,
                 std::string const& variable, ValueType value)
{
  if (infoType == OutSet) {
    makefile.AddDefinition(variable, value ? "1" : "0");
  } else // if(infoType == OutValue)
  {
    if (value) {
      makefile.AddDefinition(variable, value);
    } else {
      makefile.RemoveDefinition(variable);
    }
  }
  return true;
}
template <>
bool StoreResult(OutType infoType, cmMakefile& makefile,
                 std::string const& variable, std::nullptr_t value)
{
  return StoreResult(infoType, makefile, variable, cmValue(value));
}

bool HandleGlobalMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName)
{
  if (!name.empty()) {
    status.SetError("given name for GLOBAL scope.");
    return false;
  }

  // Get the property.
  cmake* cm = status.GetMakefile().GetCMakeInstance();
  return StoreResult(infoType, status.GetMakefile(), variable,
                     cm->GetState()->GetGlobalProperty(propertyName));
}

bool HandleDirectoryMode(cmExecutionStatus& status, std::string const& name,
                         OutType infoType, std::string const& variable,
                         std::string const& propertyName)
{
  // Default to the current directory.
  cmMakefile* mf = &status.GetMakefile();

  // Lookup the directory if given.
  if (!name.empty()) {
    // Construct the directory name.  Interpret relative paths with
    // respect to the current directory.
    std::string dir = cmSystemTools::CollapseFullPath(
      name, status.GetMakefile().GetCurrentSourceDirectory());

    // Lookup the generator.
    mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
    if (!mf) {
      // Could not find the directory.
      status.SetError(
        "DIRECTORY scope provided but requested directory was not found. "
        "This could be because the directory argument was invalid or, "
        "it is valid but has not been processed yet.");
      return false;
    }
  }

  // Get the property.
  return StoreResult(infoType, status.GetMakefile(), variable,
                     mf->GetProperty(propertyName));
}

bool HandleTargetMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName)
{
  if (name.empty()) {
    status.SetError("not given name for TARGET scope.");
    return false;
  }

  if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
    if (propertyName == "ALIASED_TARGET" || propertyName == "ALIAS_GLOBAL") {
      if (status.GetMakefile().IsAlias(name)) {
        if (propertyName == "ALIASED_TARGET") {

          return StoreResult(infoType, status.GetMakefile(), variable,
                             target->GetName().c_str());
        }
        if (propertyName == "ALIAS_GLOBAL") {
          return StoreResult(
            infoType, status.GetMakefile(), variable,
            status.GetMakefile().GetGlobalGenerator()->IsAlias(name)
              ? "TRUE"
              : "FALSE");
        }
      }
      return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
    }
    cmValue prop =
      target->GetComputedProperty(propertyName, status.GetMakefile());
    if (!prop) {
      prop = target->GetProperty(propertyName);
    }
    return StoreResult(infoType, status.GetMakefile(), variable, prop);
  }
  status.SetError(cmStrCat("could not find TARGET ", name,
                           ".  Perhaps it has not yet been created."));
  return false;
}

bool HandleFileSetMode(cmExecutionStatus& status, std::string const& name,
                       OutType infoType, std::string const& variable,
                       std::string const& propertyName, cmTarget* target)
{
  if (name.empty()) {
    status.SetError("not given name for FILE_SET scope.");
    return false;
  }

  if (cmFileSet* fileSet = target->GetFileSet(name)) {
    cmValue prop = fileSet->GetProperty(propertyName);
    return StoreResult(infoType, status.GetMakefile(), variable, prop);
  }
  status.SetError(cmStrCat("could not find FILE_SET ", name, " for TARGET ",
                           target->GetName(),
                           ".  Perhaps it has not yet been created."));
  return false;
}

bool HandleSourceMode(cmExecutionStatus& status, std::string const& name,
                      OutType infoType, std::string const& variable,
                      std::string const& propertyName,
                      cmMakefile& directory_makefile,
                      bool const source_file_paths_should_be_absolute)
{
  if (name.empty()) {
    status.SetError("not given name for SOURCE scope.");
    return false;
  }

  // Special handling for GENERATED property.
  // Note: Only, if CMP0163 is set to NEW!
  if (propertyName == "GENERATED"_s) {
    auto& mf = status.GetMakefile();
    auto cmp0163 = directory_makefile.GetPolicyStatus(cmPolicies::CMP0163);
    bool const cmp0163new =
      cmp0163 != cmPolicies::OLD && cmp0163 != cmPolicies::WARN;
    if (cmp0163new) {
      return GetPropertyCommand::GetSourceFilePropertyGENERATED(
        name, mf, [infoType, &variable, &mf](bool isGenerated) -> bool {
          // Set the value on the original Makefile scope, not the scope of the
          // requested directory.
          return StoreResult(infoType, mf, variable,
                             (isGenerated) ? cmValue("1") : cmValue("0"));
        });
    }
  }

  // Get the source file.
  std::string const source_file_absolute_path =
    SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
      status, name, source_file_paths_should_be_absolute);
  if (cmSourceFile* sf =
        directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
    // Set the value on the original Makefile scope, not the scope of the
    // requested directory.
    return StoreResult(infoType, status.GetMakefile(), variable,
                       sf->GetPropertyForUser(propertyName));
  }
  status.SetError(
    cmStrCat("given SOURCE name that could not be found or created: ",
             source_file_absolute_path));
  return false;
}

bool HandleTestMode(cmExecutionStatus& status, std::string const& name,
                    OutType infoType, std::string const& variable,
                    std::string const& propertyName, cmMakefile& test_makefile)
{
  if (name.empty()) {
    status.SetError("not given name for TEST scope.");
    return false;
  }

  // Loop over all tests looking for matching names.
  if (cmTest* test = test_makefile.GetTest(name)) {
    return StoreResult(infoType, status.GetMakefile(), variable,
                       test->GetProperty(propertyName));
  }

  // If not found it is an error.
  status.SetError(cmStrCat("given TEST name that does not exist: ", name));
  return false;
}

bool HandleVariableMode(cmExecutionStatus& status, std::string const& name,
                        OutType infoType, std::string const& variable,
                        std::string const& propertyName)
{
  if (!name.empty()) {
    status.SetError("given name for VARIABLE scope.");
    return false;
  }

  return StoreResult(infoType, status.GetMakefile(), variable,
                     status.GetMakefile().GetDefinition(propertyName));
}

bool HandleCacheMode(cmExecutionStatus& status, std::string const& name,
                     OutType infoType, std::string const& variable,
                     std::string const& propertyName)
{
  if (name.empty()) {
    status.SetError("not given name for CACHE scope.");
    return false;
  }

  cmValue value = nullptr;
  if (status.GetMakefile().GetState()->GetCacheEntryValue(name)) {
    value = status.GetMakefile().GetState()->GetCacheEntryProperty(
      name, propertyName);
  }
  StoreResult(infoType, status.GetMakefile(), variable, value);
  return true;
}

bool HandleInstallMode(cmExecutionStatus& status, std::string const& name,
                       OutType infoType, std::string const& variable,
                       std::string const& propertyName)
{
  if (name.empty()) {
    status.SetError("not given name for INSTALL scope.");
    return false;
  }

  // Get the installed file.
  cmake* cm = status.GetMakefile().GetCMakeInstance();

  if (cmInstalledFile* file =
        cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) {
    std::string value;
    bool isSet = file->GetProperty(propertyName, value);

    return StoreResult(infoType, status.GetMakefile(), variable,
                       isSet ? value.c_str() : nullptr);
  }
  status.SetError(
    cmStrCat("given INSTALL name that could not be found or created: ", name));
  return false;
}
}
