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

#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.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 "cmake.h"

class cmMessenger;

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

// Implementation of result storage.
bool StoreResult(OutType infoType, cmMakefile& makefile,
                 const std::string& variable, const char* value);

// Implementation of each property type.
bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
                      OutType infoType, const std::string& variable,
                      const std::string& propertyName);
bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
                         OutType infoType, const std::string& variable,
                         const std::string& propertyName);
bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
                      OutType infoType, const std::string& variable,
                      const std::string& propertyName);
bool HandleSourceMode(cmExecutionStatus& status, const std::string& name,
                      OutType infoType, const std::string& variable,
                      const std::string& propertyName,
                      cmMakefile& directory_makefile,
                      bool source_file_paths_should_be_absolute);
bool HandleTestMode(cmExecutionStatus& status, const std::string& name,
                    OutType infoType, const std::string& variable,
                    const std::string& propertyName);
bool HandleVariableMode(cmExecutionStatus& status, const std::string& name,
                        OutType infoType, const std::string& variable,
                        const std::string& propertyName);
bool HandleCacheMode(cmExecutionStatus& status, const std::string& name,
                     OutType infoType, const std::string& variable,
                     const std::string& propertyName);
bool HandleInstallMode(cmExecutionStatus& status, const std::string& name,
                       OutType infoType, const std::string& variable,
                       const std::string& 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.
  const std::string variable = args[0];

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

  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;

  // 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] == "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, SOURCE, TEST, VARIABLE, CACHE, INSTALL."));
    return false;
  }

  // Parse remaining arguments.
  enum Doing
  {
    DoingNone,
    DoingName,
    DoingProperty,
    DoingType,
    DoingSourceDirectory,
    DoingSourceTargetDirectory
  };
  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::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 == 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 == 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;
  }

  std::vector<cmMakefile*> source_file_directory_makefiles;
  bool file_scopes_handled =
    SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
      status, source_file_directory_option_enabled,
      source_file_target_option_enabled, source_file_directories,
      source_file_target_directories, source_file_directory_makefiles);
  if (!file_scopes_handled) {
    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();
    } else {
      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();
    } else {
      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.
    cmMakefile& directory_scope_mf = *(source_file_directory_makefiles[0]);
    bool source_file_paths_should_be_absolute =
      source_file_directory_option_enabled ||
      source_file_target_option_enabled;

    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::SOURCE_FILE:
        return HandleSourceMode(status, name, infoType, variable, propertyName,
                                directory_scope_mf,
                                source_file_paths_should_be_absolute);
      case cmProperty::TEST:
        return HandleTestMode(status, name, infoType, variable, propertyName);
      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 {

bool StoreResult(OutType infoType, cmMakefile& makefile,
                 const std::string& variable, const char* 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;
}

bool HandleGlobalMode(cmExecutionStatus& status, const std::string& name,
                      OutType infoType, const std::string& variable,
                      const std::string& 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,
    cmToCStr(cm->GetState()->GetGlobalProperty(propertyName)));
}

bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
                         OutType infoType, const std::string& variable,
                         const std::string& 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;
    }
  }

  if (propertyName == "DEFINITIONS") {
    switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) {
      case cmPolicies::WARN:
        mf->IssueMessage(MessageType::AUTHOR_WARNING,
                         cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        return StoreResult(infoType, status.GetMakefile(), variable,
                           mf->GetDefineFlagsCMP0059());
      case cmPolicies::NEW:
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
        break;
    }
  }

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

bool HandleTargetMode(cmExecutionStatus& status, const std::string& name,
                      OutType infoType, const std::string& variable,
                      const std::string& 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);
    }
    cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
    cmMessenger* messenger = status.GetMakefile().GetMessenger();
    cmProp prop = target->GetComputedProperty(propertyName, messenger, bt);
    if (!prop) {
      prop = target->GetProperty(propertyName);
    }
    return StoreResult(infoType, status.GetMakefile(), variable,
                       cmToCStr(prop));
  }
  status.SetError(cmStrCat("could not find TARGET ", name,
                           ".  Perhaps it has not yet been created."));
  return false;
}

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

  // Get the source file.
  const std::string source_file_absolute_path =
    SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded(
      status, name, source_file_paths_should_be_absolute);
  if (cmSourceFile* sf =
        directory_makefile.GetOrCreateSource(source_file_absolute_path)) {
    return StoreResult(infoType, status.GetMakefile(), variable,
                       cmToCStr(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, const std::string& name,
                    OutType infoType, const std::string& variable,
                    const std::string& propertyName)
{
  if (name.empty()) {
    status.SetError("not given name for TEST scope.");
    return false;
  }

  // Loop over all tests looking for matching names.
  if (cmTest* test = status.GetMakefile().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, const std::string& name,
                        OutType infoType, const std::string& variable,
                        const std::string& propertyName)
{
  if (!name.empty()) {
    status.SetError("given name for VARIABLE scope.");
    return false;
  }

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

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

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

bool HandleInstallMode(cmExecutionStatus& status, const std::string& name,
                       OutType infoType, const std::string& variable,
                       const std::string& 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;
}
}
