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

#include "cmSystemTools.h"

#include <utility>

// Table of valid permissions.
const char* cmInstallCommandArguments::PermissionsTable[] = {
  "OWNER_READ",    "OWNER_WRITE",   "OWNER_EXECUTE", "GROUP_READ",
  "GROUP_WRITE",   "GROUP_EXECUTE", "WORLD_READ",    "WORLD_WRITE",
  "WORLD_EXECUTE", "SETUID",        "SETGID",        nullptr
};

const std::string cmInstallCommandArguments::EmptyString;

cmInstallCommandArguments::cmInstallCommandArguments(
  const std::string& defaultComponent)
  : Parser()
  , ArgumentGroup()
  , Destination(&Parser, "DESTINATION", &ArgumentGroup)
  , Component(&Parser, "COMPONENT", &ArgumentGroup)
  , NamelinkComponent(&Parser, "NAMELINK_COMPONENT", &ArgumentGroup)
  , ExcludeFromAll(&Parser, "EXCLUDE_FROM_ALL", &ArgumentGroup)
  , Rename(&Parser, "RENAME", &ArgumentGroup)
  , Permissions(&Parser, "PERMISSIONS", &ArgumentGroup)
  , Configurations(&Parser, "CONFIGURATIONS", &ArgumentGroup)
  , Optional(&Parser, "OPTIONAL", &ArgumentGroup)
  , NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup)
  , NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup)
  , GenericArguments(nullptr)
  , DefaultComponentName(defaultComponent)
{
}

const std::string& cmInstallCommandArguments::GetDestination() const
{
  if (!this->DestinationString.empty()) {
    return this->DestinationString;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetDestination();
  }
  return EmptyString;
}

const std::string& cmInstallCommandArguments::GetComponent() const
{
  if (!this->Component.GetString().empty()) {
    return this->Component.GetString();
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetComponent();
  }
  if (!this->DefaultComponentName.empty()) {
    return this->DefaultComponentName;
  }
  static std::string unspecifiedComponent = "Unspecified";
  return unspecifiedComponent;
}

const std::string& cmInstallCommandArguments::GetNamelinkComponent() const
{
  if (!this->NamelinkComponent.GetString().empty()) {
    return this->NamelinkComponent.GetString();
  }
  return this->GetComponent();
}

const std::string& cmInstallCommandArguments::GetRename() const
{
  if (!this->Rename.GetString().empty()) {
    return this->Rename.GetString();
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetRename();
  }
  return EmptyString;
}

const std::string& cmInstallCommandArguments::GetPermissions() const
{
  if (!this->PermissionsString.empty()) {
    return this->PermissionsString;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetPermissions();
  }
  return EmptyString;
}

bool cmInstallCommandArguments::GetOptional() const
{
  if (this->Optional.IsEnabled()) {
    return true;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetOptional();
  }
  return false;
}

bool cmInstallCommandArguments::GetExcludeFromAll() const
{
  if (this->ExcludeFromAll.IsEnabled()) {
    return true;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetExcludeFromAll();
  }
  return false;
}

bool cmInstallCommandArguments::GetNamelinkOnly() const
{
  if (this->NamelinkOnly.IsEnabled()) {
    return true;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetNamelinkOnly();
  }
  return false;
}

bool cmInstallCommandArguments::GetNamelinkSkip() const
{
  if (this->NamelinkSkip.IsEnabled()) {
    return true;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetNamelinkSkip();
  }
  return false;
}

bool cmInstallCommandArguments::HasNamelinkComponent() const
{
  if (!this->NamelinkComponent.GetString().empty()) {
    return true;
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->HasNamelinkComponent();
  }
  return false;
}

const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
  const
{
  if (!this->Configurations.GetVector().empty()) {
    return this->Configurations.GetVector();
  }
  if (this->GenericArguments != nullptr) {
    return this->GenericArguments->GetConfigurations();
  }
  return this->Configurations.GetVector();
}

bool cmInstallCommandArguments::Finalize()
{
  if (!this->CheckPermissions()) {
    return false;
  }
  this->DestinationString = this->Destination.GetString();
  cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
  return true;
}

void cmInstallCommandArguments::Parse(const std::vector<std::string>* args,
                                      std::vector<std::string>* unconsumedArgs)
{
  this->Parser.Parse(args, unconsumedArgs);
}

bool cmInstallCommandArguments::CheckPermissions()
{
  this->PermissionsString.clear();
  for (std::string const& perm : this->Permissions.GetVector()) {
    if (!this->CheckPermissions(perm, this->PermissionsString)) {
      return false;
    }
  }
  return true;
}

bool cmInstallCommandArguments::CheckPermissions(
  const std::string& onePermission, std::string& permissions)
{
  // Check the permission against the table.
  for (const char** valid = cmInstallCommandArguments::PermissionsTable;
       *valid; ++valid) {
    if (onePermission == *valid) {
      // This is a valid permission.
      permissions += " ";
      permissions += onePermission;
      return true;
    }
  }
  // This is not a valid permission.
  return false;
}

cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument()
{
}

const std::vector<std::string>&
cmInstallCommandIncludesArgument::GetIncludeDirs() const
{
  return this->IncludeDirs;
}

void cmInstallCommandIncludesArgument::Parse(
  const std::vector<std::string>* args, std::vector<std::string>*)
{
  if (args->empty()) {
    return;
  }
  std::vector<std::string>::const_iterator it = args->begin();
  ++it;
  for (; it != args->end(); ++it) {
    std::string dir = *it;
    cmSystemTools::ConvertToUnixSlashes(dir);
    this->IncludeDirs.push_back(std::move(dir));
  }
}
