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

#include "cmStateDirectory.h"

#include <algorithm>
#include <cassert>
#include <vector>

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

#include "cmAlgorithms.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStatePrivate.h"
#include "cmValue.h"

static std::string const kBINARY_DIR = "BINARY_DIR";
static std::string const kBUILDSYSTEM_TARGETS = "BUILDSYSTEM_TARGETS";
static std::string const kSOURCE_DIR = "SOURCE_DIR";
static std::string const kSUBDIRECTORIES = "SUBDIRECTORIES";

std::string const& cmStateDirectory::GetCurrentSource() const
{
  return this->DirectoryState->Location;
}

void cmStateDirectory::SetCurrentSource(std::string const& dir)
{
  this->DirectoryState->Location = dir;
  this->Snapshot_.SetDefinition("CMAKE_CURRENT_SOURCE_DIR",
                                this->DirectoryState->Location);
}

std::string const& cmStateDirectory::GetCurrentBinary() const
{
  return this->DirectoryState->OutputLocation;
}

void cmStateDirectory::SetCurrentBinary(std::string const& dir)
{
  this->DirectoryState->OutputLocation = dir;
  this->Snapshot_.SetDefinition("CMAKE_CURRENT_BINARY_DIR",
                                this->DirectoryState->OutputLocation);
}

cmStateDirectory::cmStateDirectory(
  cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
  cmStateSnapshot const& snapshot)
  : DirectoryState(iter)
  , Snapshot_(snapshot)
{
}

template <typename T, typename U>
cmBTStringRange GetPropertyContent(T const& content, U contentEndPosition)
{
  auto end = content.begin() + contentEndPosition;

  auto rbegin = cm::make_reverse_iterator(end);
  rbegin = std::find(rbegin, content.rend(), cmStateDetail::PropertySentinel);

  return cmMakeRange(rbegin.base(), end);
}

template <typename T, typename U>
void AppendEntry(T& content, U& endContentPosition,
                 const BT<std::string>& value)
{
  if (value.Value.empty()) {
    return;
  }

  assert(endContentPosition == content.size());

  content.push_back(value);

  endContentPosition = content.size();
}

template <typename T, typename U>
void SetContent(T& content, U& endContentPosition, const BT<std::string>& vec)
{
  assert(endContentPosition == content.size());

  content.resize(content.size() + 2);

  content.back() = vec;

  endContentPosition = content.size();
}

template <typename T, typename U>
void ClearContent(T& content, U& endContentPosition)
{
  assert(endContentPosition == content.size());

  content.resize(content.size() + 1);

  endContentPosition = content.size();
}

cmBTStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const
{
  return GetPropertyContent(
    this->DirectoryState->IncludeDirectories,
    this->Snapshot_.Position->IncludeDirectoryPosition);
}

void cmStateDirectory::AppendIncludeDirectoriesEntry(
  const BT<std::string>& vec)
{
  AppendEntry(this->DirectoryState->IncludeDirectories,
              this->Snapshot_.Position->IncludeDirectoryPosition, vec);
}

void cmStateDirectory::PrependIncludeDirectoriesEntry(
  const BT<std::string>& vec)
{
  auto entryEnd = this->DirectoryState->IncludeDirectories.begin() +
    this->Snapshot_.Position->IncludeDirectoryPosition;

  auto rend = this->DirectoryState->IncludeDirectories.rend();
  auto rbegin = cm::make_reverse_iterator(entryEnd);
  rbegin = std::find(rbegin, rend, cmStateDetail::PropertySentinel);

  auto entryIt = rbegin.base();

  this->DirectoryState->IncludeDirectories.insert(entryIt, vec);

  this->Snapshot_.Position->IncludeDirectoryPosition =
    this->DirectoryState->IncludeDirectories.size();
}

void cmStateDirectory::SetIncludeDirectories(const BT<std::string>& vec)
{
  SetContent(this->DirectoryState->IncludeDirectories,
             this->Snapshot_.Position->IncludeDirectoryPosition, vec);
}

void cmStateDirectory::ClearIncludeDirectories()
{
  ClearContent(this->DirectoryState->IncludeDirectories,
               this->Snapshot_.Position->IncludeDirectoryPosition);
}

cmBTStringRange cmStateDirectory::GetCompileDefinitionsEntries() const
{
  return GetPropertyContent(
    this->DirectoryState->CompileDefinitions,
    this->Snapshot_.Position->CompileDefinitionsPosition);
}

void cmStateDirectory::AppendCompileDefinitionsEntry(
  const BT<std::string>& vec)
{
  AppendEntry(this->DirectoryState->CompileDefinitions,
              this->Snapshot_.Position->CompileDefinitionsPosition, vec);
}

void cmStateDirectory::SetCompileDefinitions(const BT<std::string>& vec)
{
  SetContent(this->DirectoryState->CompileDefinitions,
             this->Snapshot_.Position->CompileDefinitionsPosition, vec);
}

void cmStateDirectory::ClearCompileDefinitions()
{
  ClearContent(this->DirectoryState->CompileDefinitions,
               this->Snapshot_.Position->CompileDefinitionsPosition);
}

cmBTStringRange cmStateDirectory::GetCompileOptionsEntries() const
{
  return GetPropertyContent(this->DirectoryState->CompileOptions,
                            this->Snapshot_.Position->CompileOptionsPosition);
}

void cmStateDirectory::AppendCompileOptionsEntry(const BT<std::string>& vec)
{
  AppendEntry(this->DirectoryState->CompileOptions,
              this->Snapshot_.Position->CompileOptionsPosition, vec);
}

void cmStateDirectory::SetCompileOptions(const BT<std::string>& vec)
{
  SetContent(this->DirectoryState->CompileOptions,
             this->Snapshot_.Position->CompileOptionsPosition, vec);
}

void cmStateDirectory::ClearCompileOptions()
{
  ClearContent(this->DirectoryState->CompileOptions,
               this->Snapshot_.Position->CompileOptionsPosition);
}

cmBTStringRange cmStateDirectory::GetLinkOptionsEntries() const
{
  return GetPropertyContent(this->DirectoryState->LinkOptions,
                            this->Snapshot_.Position->LinkOptionsPosition);
}

void cmStateDirectory::AppendLinkOptionsEntry(const BT<std::string>& vec)
{
  AppendEntry(this->DirectoryState->LinkOptions,
              this->Snapshot_.Position->LinkOptionsPosition, vec);
}

void cmStateDirectory::SetLinkOptions(const BT<std::string>& vec)
{
  SetContent(this->DirectoryState->LinkOptions,
             this->Snapshot_.Position->LinkOptionsPosition, vec);
}

void cmStateDirectory::ClearLinkOptions()
{
  ClearContent(this->DirectoryState->LinkOptions,
               this->Snapshot_.Position->LinkOptionsPosition);
}

cmBTStringRange cmStateDirectory::GetLinkDirectoriesEntries() const
{
  return GetPropertyContent(this->DirectoryState->LinkDirectories,
                            this->Snapshot_.Position->LinkDirectoriesPosition);
}

void cmStateDirectory::AppendLinkDirectoriesEntry(const BT<std::string>& vec)
{
  AppendEntry(this->DirectoryState->LinkDirectories,
              this->Snapshot_.Position->LinkDirectoriesPosition, vec);
}
void cmStateDirectory::PrependLinkDirectoriesEntry(const BT<std::string>& vec)
{
  auto entryEnd = this->DirectoryState->LinkDirectories.begin() +
    this->Snapshot_.Position->LinkDirectoriesPosition;

  auto rend = this->DirectoryState->LinkDirectories.rend();
  auto rbegin = cm::make_reverse_iterator(entryEnd);
  rbegin = std::find(rbegin, rend, cmStateDetail::PropertySentinel);

  auto entryIt = rbegin.base();

  this->DirectoryState->LinkDirectories.insert(entryIt, vec);

  this->Snapshot_.Position->LinkDirectoriesPosition =
    this->DirectoryState->LinkDirectories.size();
}

void cmStateDirectory::SetLinkDirectories(const BT<std::string>& vec)
{
  SetContent(this->DirectoryState->LinkDirectories,
             this->Snapshot_.Position->LinkDirectoriesPosition, vec);
}

void cmStateDirectory::ClearLinkDirectories()
{
  ClearContent(this->DirectoryState->LinkDirectories,
               this->Snapshot_.Position->LinkDirectoriesPosition);
}

void cmStateDirectory::SetProperty(std::string const& prop, cmValue value,
                                   cmListFileBacktrace const& lfbt)
{
  if (prop == "INCLUDE_DIRECTORIES") {
    if (!value) {
      this->ClearIncludeDirectories();
      return;
    }
    this->SetIncludeDirectories(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "COMPILE_OPTIONS") {
    if (!value) {
      this->ClearCompileOptions();
      return;
    }
    this->SetCompileOptions(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "COMPILE_DEFINITIONS") {
    if (!value) {
      this->ClearCompileDefinitions();
      return;
    }
    this->SetCompileDefinitions(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "LINK_OPTIONS") {
    if (!value) {
      this->ClearLinkOptions();
      return;
    }
    this->SetLinkOptions(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "LINK_DIRECTORIES") {
    if (!value) {
      this->ClearLinkDirectories();
      return;
    }
    this->SetLinkDirectories(BT<std::string>(value, lfbt));
    return;
  }

  this->DirectoryState->Properties.SetProperty(prop, value);
}

void cmStateDirectory::AppendProperty(std::string const& prop,
                                      std::string const& value, bool asString,
                                      cmListFileBacktrace const& lfbt)
{
  if (prop == "INCLUDE_DIRECTORIES") {
    this->AppendIncludeDirectoriesEntry(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "COMPILE_OPTIONS") {
    this->AppendCompileOptionsEntry(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "COMPILE_DEFINITIONS") {
    this->AppendCompileDefinitionsEntry(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "LINK_OPTIONS") {
    this->AppendLinkOptionsEntry(BT<std::string>(value, lfbt));
    return;
  }
  if (prop == "LINK_DIRECTORIES") {
    this->AppendLinkDirectoriesEntry(BT<std::string>(value, lfbt));
    return;
  }

  this->DirectoryState->Properties.AppendProperty(prop, value, asString);
}

cmValue cmStateDirectory::GetProperty(std::string const& prop) const
{
  bool const chain =
    this->Snapshot_.State->IsPropertyChained(prop, cmProperty::DIRECTORY);
  return this->GetProperty(prop, chain);
}

cmValue cmStateDirectory::GetProperty(std::string const& prop,
                                      bool chain) const
{
  static std::string output;
  output.clear();
  if (prop == "PARENT_DIRECTORY") {
    cmStateSnapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent();
    if (parent.IsValid()) {
      return cmValue(parent.GetDirectory().GetCurrentSource());
    }
    return cmValue(output);
  }
  if (prop == kBINARY_DIR) {
    output = this->GetCurrentBinary();
    return cmValue(output);
  }
  if (prop == kSOURCE_DIR) {
    output = this->GetCurrentSource();
    return cmValue(output);
  }
  if (prop == kSUBDIRECTORIES) {
    std::vector<std::string> child_dirs;
    std::vector<cmStateSnapshot> const& children =
      this->DirectoryState->Children;
    child_dirs.reserve(children.size());
    for (cmStateSnapshot const& ci : children) {
      child_dirs.push_back(ci.GetDirectory().GetCurrentSource());
    }
    output = cmList::to_string(child_dirs);
    return cmValue(output);
  }
  if (prop == kBUILDSYSTEM_TARGETS) {
    output = cmList::to_string(this->DirectoryState->NormalTargetNames);
    return cmValue(output);
  }
  if (prop == "IMPORTED_TARGETS"_s) {
    output = cmList::to_string(this->DirectoryState->ImportedTargetNames);
    return cmValue(output);
  }

  if (prop == "LISTFILE_STACK") {
    std::vector<std::string> listFiles;
    cmStateSnapshot snp = this->Snapshot_;
    while (snp.IsValid()) {
      listFiles.push_back(snp.GetExecutionListFile());
      snp = snp.GetCallStackParent();
    }
    std::reverse(listFiles.begin(), listFiles.end());
    output = cmList::to_string(listFiles);
    return cmValue(output);
  }
  if (prop == "CACHE_VARIABLES") {
    output = cmList::to_string(this->Snapshot_.State->GetCacheEntryKeys());
    return cmValue(output);
  }
  if (prop == "VARIABLES") {
    std::vector<std::string> res = this->Snapshot_.ClosureKeys();
    cm::append(res, this->Snapshot_.State->GetCacheEntryKeys());
    std::sort(res.begin(), res.end());
    output = cmList::to_string(res);
    return cmValue(output);
  }
  if (prop == "INCLUDE_DIRECTORIES") {
    output = cmList::to_string(this->GetIncludeDirectoriesEntries());
    return cmValue(output);
  }
  if (prop == "COMPILE_OPTIONS") {
    output = cmList::to_string(this->GetCompileOptionsEntries());
    return cmValue(output);
  }
  if (prop == "COMPILE_DEFINITIONS") {
    output = cmList::to_string(this->GetCompileDefinitionsEntries());
    return cmValue(output);
  }
  if (prop == "LINK_OPTIONS") {
    output = cmList::to_string(this->GetLinkOptionsEntries());
    return cmValue(output);
  }
  if (prop == "LINK_DIRECTORIES") {
    output = cmList::to_string(this->GetLinkDirectoriesEntries());
    return cmValue(output);
  }

  cmValue retVal = this->DirectoryState->Properties.GetPropertyValue(prop);
  if (!retVal && chain) {
    cmStateSnapshot parentSnapshot =
      this->Snapshot_.GetBuildsystemDirectoryParent();
    if (parentSnapshot.IsValid()) {
      return parentSnapshot.GetDirectory().GetProperty(prop, chain);
    }
    return this->Snapshot_.State->GetGlobalProperty(prop);
  }

  return retVal;
}

bool cmStateDirectory::GetPropertyAsBool(std::string const& prop) const
{
  return this->GetProperty(prop).IsOn();
}

std::vector<std::string> cmStateDirectory::GetPropertyKeys() const
{
  return this->DirectoryState->Properties.GetKeys();
}

void cmStateDirectory::AddNormalTargetName(std::string const& name)
{
  this->DirectoryState->NormalTargetNames.push_back(name);
}

void cmStateDirectory::AddImportedTargetName(std::string const& name)
{
  this->DirectoryState->ImportedTargetNames.emplace_back(name);
}
