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

#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmTarget.h"
#include "cmake.h"

cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
  : Makefile(&status.GetMakefile())
  , Status(status)
{
}

void cmTargetPropCommandBase::SetError(std::string const& e)
{
  this->Status.SetError(e);
}

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

  if (this->Makefile->IsAlias(args[0])) {
    this->SetError("can not be used on an ALIAS target.");
    return false;
  }
  // Lookup the target for which property-values are specified.
  this->Target =
    this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
      args[0]);
  if (!this->Target) {
    this->Target = this->Makefile->FindTargetToUse(args[0]);
  }
  if (!this->Target) {
    this->HandleMissingTarget(args[0]);
    return false;
  }
  if ((this->Target->GetType() != cmStateEnums::EXECUTABLE) &&
      (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::UNKNOWN_LIBRARY)) {
    this->SetError("called with non-compilable target type");
    return false;
  }

  bool system = false;
  unsigned int argIndex = 1;

  if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
    if (args.size() < 3) {
      this->SetError("called with incorrect number of arguments");
      return false;
    }
    system = true;
    ++argIndex;
  }

  bool prepend = false;
  if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
    if (args.size() < 3) {
      this->SetError("called with incorrect number of arguments");
      return false;
    }
    prepend = true;
    ++argIndex;
  }

  if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
    if (args.size() != 3) {
      this->SetError("called with incorrect number of arguments");
      return false;
    }
    ++argIndex;

    this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]);
    ++argIndex;
  }

  this->Property = prop;

  while (argIndex < args.size()) {
    if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
      return false;
    }
  }
  return true;
}

bool cmTargetPropCommandBase::ProcessContentArgs(
  std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
  bool system)
{
  std::string const& scope = args[argIndex];

  if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
    this->SetError("called with invalid arguments");
    return false;
  }

  ++argIndex;

  std::vector<std::string> content;

  for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
    if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
        args[i] == "INTERFACE") {
      break;
    }
    content.push_back(args[i]);
  }
  if (!content.empty()) {
    if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
        scope != "INTERFACE") {
      this->SetError("may only set INTERFACE properties on INTERFACE targets");
      return false;
    }
    if (this->Target->IsImported() && scope != "INTERFACE") {
      this->SetError("may only set INTERFACE properties on IMPORTED targets");
      return false;
    }
  }
  return this->PopulateTargetProperies(scope, content, prepend, system);
}

bool cmTargetPropCommandBase::PopulateTargetProperies(
  const std::string& scope, const std::vector<std::string>& content,
  bool prepend, bool system)
{
  if (content.empty()) {
    return true;
  }
  if (scope == "PRIVATE" || scope == "PUBLIC") {
    if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
      return false;
    }
  }
  if (scope == "INTERFACE" || scope == "PUBLIC") {
    this->HandleInterfaceContent(this->Target, content, prepend, system);
  }
  return true;
}

void cmTargetPropCommandBase::HandleInterfaceContent(
  cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
{
  if (prepend) {
    const std::string propName = std::string("INTERFACE_") + this->Property;
    const char* propValue = tgt->GetProperty(propName);
    const std::string totalContent = this->Join(content) +
      (propValue ? std::string(";") + propValue : std::string());
    tgt->SetProperty(propName, totalContent);
  } else {
    tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));
  }
}
