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

#include <sstream>

#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTest.h"
#include "cmake.h"

class cmExecutionStatus;

cmSetPropertyCommand::cmSetPropertyCommand()
{
  this->AppendMode = false;
  this->AppendAsString = false;
  this->Remove = true;
}

bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args,
                                       cmExecutionStatus&)
{
  if (args.size() < 2) {
    this->SetError("called with incorrect number of arguments");
    return false;
  }

  // Get the scope on which to set the property.
  std::string const& scopeName = args.front();
  cmProperty::ScopeType scope;
  if (scopeName == "GLOBAL") {
    scope = cmProperty::GLOBAL;
  } else if (scopeName == "DIRECTORY") {
    scope = cmProperty::DIRECTORY;
  } else if (scopeName == "TARGET") {
    scope = cmProperty::TARGET;
  } else if (scopeName == "SOURCE") {
    scope = cmProperty::SOURCE_FILE;
  } else if (scopeName == "TEST") {
    scope = cmProperty::TEST;
  } else if (scopeName == "CACHE") {
    scope = cmProperty::CACHE;
  } else if (scopeName == "INSTALL") {
    scope = cmProperty::INSTALL;
  } else {
    std::ostringstream e;
    e << "given invalid scope " << scopeName << ".  "
      << "Valid scopes are GLOBAL, DIRECTORY, "
         "TARGET, SOURCE, TEST, CACHE, INSTALL.";
    this->SetError(e.str());
    return false;
  }

  // Parse the rest of the arguments up to the values.
  enum Doing
  {
    DoingNone,
    DoingNames,
    DoingProperty,
    DoingValues
  };
  Doing doing = DoingNames;
  const char* sep = "";
  for (std::string const& arg : cmMakeRange(args).advance(1)) {
    if (arg == "PROPERTY") {
      doing = DoingProperty;
    } else if (arg == "APPEND") {
      doing = DoingNone;
      this->AppendMode = true;
      this->Remove = false;
      this->AppendAsString = false;
    } else if (arg == "APPEND_STRING") {
      doing = DoingNone;
      this->AppendMode = true;
      this->Remove = false;
      this->AppendAsString = true;
    } else if (doing == DoingNames) {
      this->Names.insert(arg);
    } else if (doing == DoingProperty) {
      this->PropertyName = arg;
      doing = DoingValues;
    } else if (doing == DoingValues) {
      this->PropertyValue += sep;
      sep = ";";
      this->PropertyValue += arg;
      this->Remove = false;
    } else {
      std::ostringstream e;
      e << "given invalid argument \"" << arg << "\".";
      this->SetError(e.str());
      return false;
    }
  }

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

  // Dispatch property setting.
  switch (scope) {
    case cmProperty::GLOBAL:
      return this->HandleGlobalMode();
    case cmProperty::DIRECTORY:
      return this->HandleDirectoryMode();
    case cmProperty::TARGET:
      return this->HandleTargetMode();
    case cmProperty::SOURCE_FILE:
      return this->HandleSourceMode();
    case cmProperty::TEST:
      return this->HandleTestMode();
    case cmProperty::CACHE:
      return this->HandleCacheMode();
    case cmProperty::INSTALL:
      return this->HandleInstallMode();

    case cmProperty::VARIABLE:
    case cmProperty::CACHED_VARIABLE:
      break; // should never happen
  }
  return true;
}

bool cmSetPropertyCommand::HandleGlobalMode()
{
  if (!this->Names.empty()) {
    this->SetError("given names for GLOBAL scope.");
    return false;
  }

  // Set or append the property.
  cmake* cm = this->Makefile->GetCMakeInstance();
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = nullptr;
  }
  if (this->AppendMode) {
    cm->AppendProperty(name, value ? value : "", this->AppendAsString);
  } else {
    cm->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleDirectoryMode()
{
  if (this->Names.size() > 1) {
    this->SetError("allows at most one name for DIRECTORY scope.");
    return false;
  }

  // Default to the current directory.
  cmMakefile* mf = this->Makefile;

  // Lookup the directory if given.
  if (!this->Names.empty()) {
    // Construct the directory name.  Interpret relative paths with
    // respect to the current directory.
    std::string dir = *this->Names.begin();
    if (!cmSystemTools::FileIsFullPath(dir)) {
      dir = this->Makefile->GetCurrentSourceDirectory();
      dir += "/";
      dir += *this->Names.begin();
    }

    // The local generators are associated with collapsed paths.
    dir = cmSystemTools::CollapseFullPath(dir);

    mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
    if (!mf) {
      // Could not find the directory.
      this->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;
    }
  }

  // Set or append the property.
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = nullptr;
  }
  if (this->AppendMode) {
    mf->AppendProperty(name, value ? value : "", this->AppendAsString);
  } else {
    mf->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleTargetMode()
{
  for (std::string const& name : this->Names) {
    if (this->Makefile->IsAlias(name)) {
      this->SetError("can not be used on an ALIAS target.");
      return false;
    }
    if (cmTarget* target = this->Makefile->FindTargetToUse(name)) {
      // Handle the current target.
      if (!this->HandleTarget(target)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "could not find TARGET " << name
        << ".  Perhaps it has not yet been created.";
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = nullptr;
  }
  if (this->AppendMode) {
    target->AppendProperty(name, value, this->AppendAsString);
  } else {
    target->SetProperty(name, value);
  }

  // Check the resulting value.
  target->CheckProperty(name, this->Makefile);

  return true;
}

bool cmSetPropertyCommand::HandleSourceMode()
{
  for (std::string const& name : this->Names) {
    // Get the source file.
    if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(name)) {
      if (!this->HandleSource(sf)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "given SOURCE name that could not be found or created: " << name;
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = nullptr;
  }

  if (this->AppendMode) {
    sf->AppendProperty(name, value, this->AppendAsString);
  } else {
    sf->SetProperty(name, value);
  }
  return true;
}

bool cmSetPropertyCommand::HandleTestMode()
{
  // Look for tests with all names given.
  std::set<std::string>::iterator next;
  for (std::set<std::string>::iterator ni = this->Names.begin();
       ni != this->Names.end(); ni = next) {
    next = ni;
    ++next;
    if (cmTest* test = this->Makefile->GetTest(*ni)) {
      if (this->HandleTest(test)) {
        this->Names.erase(ni);
      } else {
        return false;
      }
    }
  }

  // Names that are still left were not found.
  if (!this->Names.empty()) {
    std::ostringstream e;
    e << "given TEST names that do not exist:\n";
    for (std::string const& name : this->Names) {
      e << "  " << name << "\n";
    }
    this->SetError(e.str());
    return false;
  }
  return true;
}

bool cmSetPropertyCommand::HandleTest(cmTest* test)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    value = nullptr;
  }
  if (this->AppendMode) {
    test->AppendProperty(name, value, this->AppendAsString);
  } else {
    test->SetProperty(name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleCacheMode()
{
  if (this->PropertyName == "ADVANCED") {
    if (!this->Remove && !cmSystemTools::IsOn(this->PropertyValue) &&
        !cmSystemTools::IsOff(this->PropertyValue)) {
      std::ostringstream e;
      e << "given non-boolean value \"" << this->PropertyValue
        << "\" for CACHE property \"ADVANCED\".  ";
      this->SetError(e.str());
      return false;
    }
  } else if (this->PropertyName == "TYPE") {
    if (!cmState::IsCacheEntryType(this->PropertyValue)) {
      std::ostringstream e;
      e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
      this->SetError(e.str());
      return false;
    }
  } else if (this->PropertyName != "HELPSTRING" &&
             this->PropertyName != "STRINGS" &&
             this->PropertyName != "VALUE") {
    std::ostringstream e;
    e << "given invalid CACHE property " << this->PropertyName << ".  "
      << "Settable CACHE properties are: "
      << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.";
    this->SetError(e.str());
    return false;
  }

  for (std::string const& name : this->Names) {
    // Get the source file.
    cmMakefile* mf = this->GetMakefile();
    cmake* cm = mf->GetCMakeInstance();
    const char* existingValue = cm->GetState()->GetCacheEntryValue(name);
    if (existingValue) {
      if (!this->HandleCacheEntry(name)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "could not find CACHE variable " << name
        << ".  Perhaps it has not yet been created.";
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;
  const char* value = this->PropertyValue.c_str();
  cmState* state = this->Makefile->GetState();
  if (this->Remove) {
    state->RemoveCacheEntryProperty(cacheKey, name);
  }
  if (this->AppendMode) {
    state->AppendCacheEntryProperty(cacheKey, name, value,
                                    this->AppendAsString);
  } else {
    state->SetCacheEntryProperty(cacheKey, name, value);
  }

  return true;
}

bool cmSetPropertyCommand::HandleInstallMode()
{
  cmake* cm = this->Makefile->GetCMakeInstance();

  for (std::string const& name : this->Names) {
    if (cmInstalledFile* file =
          cm->GetOrCreateInstalledFile(this->Makefile, name)) {
      if (!this->HandleInstall(file)) {
        return false;
      }
    } else {
      std::ostringstream e;
      e << "given INSTALL name that could not be found or created: " << name;
      this->SetError(e.str());
      return false;
    }
  }
  return true;
}

bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
{
  // Set or append the property.
  std::string const& name = this->PropertyName;

  cmMakefile* mf = this->Makefile;

  const char* value = this->PropertyValue.c_str();
  if (this->Remove) {
    file->RemoveProperty(name);
  } else if (this->AppendMode) {
    file->AppendProperty(mf, name, value, this->AppendAsString);
  } else {
    file->SetProperty(mf, name, value);
  }
  return true;
}
