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

#include <algorithm>
#include <cstring>
#include <iterator>
#include <utility>

#include <cmext/algorithm>

#include "cmsys/String.h"

#include "cmIDEFlagTable.h"
#include "cmList.h"
#include "cmStringAlgorithms.h"

cmIDEOptions::cmIDEOptions()
{
  this->DoingDefine = false;
  this->AllowDefine = true;
  this->DoingInclude = false;
  this->AllowSlash = false;
  this->DoingFollowing = nullptr;
  for (auto& flag : this->FlagTable) {
    flag = nullptr;
  }
}

cmIDEOptions::~cmIDEOptions() = default;

void cmIDEOptions::HandleFlag(std::string const& flag)
{
  // If the last option was -D then this option is the definition.
  if (this->DoingDefine) {
    this->DoingDefine = false;
    this->Defines.push_back(flag);
    return;
  }

  // If the last option was -I then this option is the include directory.
  if (this->DoingInclude) {
    this->DoingInclude = false;
    this->Includes.push_back(flag);
    return;
  }

  // If the last option expected a following value, this is it.
  if (this->DoingFollowing) {
    this->FlagMapUpdate(this->DoingFollowing, flag);
    this->DoingFollowing = nullptr;
    return;
  }

  // Look for known arguments.
  size_t len = flag.length();
  if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
    // Look for preprocessor definitions.
    if (this->AllowDefine && len > 1 && flag[1] == 'D') {
      if (len <= 2) {
        // The next argument will have the definition.
        this->DoingDefine = true;
      } else {
        // Store this definition.
        this->Defines.push_back(flag.substr(2));
      }
      return;
    }
    // Look for include directory.
    if (this->AllowInclude && len > 1 && flag[1] == 'I') {
      if (len <= 2) {
        // The next argument will have the include directory.
        this->DoingInclude = true;
      } else {
        // Store this include directory.
        this->Includes.push_back(flag.substr(2));
      }
      return;
    }

    // Look through the available flag tables.
    bool flag_handled = false;
    for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) {
      if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) {
        return;
      }
    }

    // If any map entry handled the flag we are done.
    if (flag_handled) {
      return;
    }
  }

  // This option is not known.  Store it in the output flags.
  this->StoreUnknownFlag(flag);
}

bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
                                  std::string const& flag, bool& flag_handled)
{
  char const* pf = flag.c_str() + 1;
  // Look for an entry in the flag table matching this flag.
  for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) {
    bool entry_found = false;
    if (entry->special & cmIDEFlagTable::UserValue) {
      // This flag table entry accepts a user-specified value.  If
      // the entry specifies UserRequired we must match only if a
      // non-empty value is given.
      int n = static_cast<int>(entry->commandFlag.length());
      if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 ||
           (entry->special & cmIDEFlagTable::CaseInsensitive &&
            cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) &&
          (!(entry->special & cmIDEFlagTable::UserRequired) ||
           static_cast<int>(strlen(pf)) > n)) {
        this->FlagMapUpdate(entry, std::string(pf + n));
        entry_found = true;
      }
    } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 ||
               (entry->special & cmIDEFlagTable::CaseInsensitive &&
                cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) {
      if (entry->special & cmIDEFlagTable::UserFollowing) {
        // This flag expects a value in the following argument.
        this->DoingFollowing = entry;
      } else {
        // This flag table entry provides a fixed value.
        this->FlagMap[entry->IDEName] = entry->value;
      }
      entry_found = true;
    }

    // If the flag has been handled by an entry not requesting a
    // search continuation we are done.
    if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) {
      return true;
    }

    // If the entry was found the flag has been handled.
    flag_handled = flag_handled || entry_found;
  }

  return false;
}

void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
                                 std::string const& new_value)
{
  if (entry->special & cmIDEFlagTable::UserIgnored) {
    // Ignore the user-specified value.
    this->FlagMap[entry->IDEName] = entry->value;
  } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
    this->FlagMap[entry->IDEName].push_back(new_value);
  } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
    this->FlagMap[entry->IDEName].append_with_space(new_value);
  } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
    this->FlagMap[entry->IDEName].append_with_comma(new_value);
  } else {
    // Use the user-specified value.
    this->FlagMap[entry->IDEName] = new_value;
  }
}

void cmIDEOptions::AddDefine(std::string const& def)
{
  this->Defines.push_back(def);
}

void cmIDEOptions::AddDefines(std::string const& defines)
{
  if (!defines.empty()) {
    // Expand the list of definitions.
    cmExpandList(defines, this->Defines);
  }
}
void cmIDEOptions::AddDefines(std::vector<std::string> const& defines)
{
  cm::append(this->Defines, defines);
}

std::vector<std::string> const& cmIDEOptions::GetDefines() const
{
  return this->Defines;
}

void cmIDEOptions::AddInclude(std::string const& include)
{
  this->Includes.push_back(include);
}

void cmIDEOptions::AddIncludes(std::string const& includes)
{
  if (!includes.empty()) {
    // Expand the list of includes.
    cmExpandList(includes, this->Includes);
  }
}
void cmIDEOptions::AddIncludes(std::vector<std::string> const& includes)
{
  cm::append(this->Includes, includes);
}

std::vector<std::string> const& cmIDEOptions::GetIncludes() const
{
  return this->Includes;
}

void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
{
  this->FlagMap[flag] = value;
}

void cmIDEOptions::AddFlag(std::string const& flag,
                           std::vector<std::string> const& value)
{
  this->FlagMap[flag] = value;
}

void cmIDEOptions::AppendFlag(std::string const& flag,
                              std::string const& value)
{
  this->FlagMap[flag].push_back(value);
}

void cmIDEOptions::AppendFlag(std::string const& flag,
                              std::vector<std::string> const& value)
{
  FlagValue& fv = this->FlagMap[flag];
  std::copy(value.begin(), value.end(), std::back_inserter(fv));
}

void cmIDEOptions::AppendFlagString(std::string const& flag,
                                    std::string const& value)
{
  this->FlagMap[flag].append_with_space(value);
}

void cmIDEOptions::RemoveFlag(std::string const& flag)
{
  this->FlagMap.erase(flag);
}

bool cmIDEOptions::HasFlag(std::string const& flag) const
{
  return this->FlagMap.find(flag) != this->FlagMap.end();
}

char const* cmIDEOptions::GetFlag(std::string const& flag) const
{
  // This method works only for single-valued flags!
  auto i = this->FlagMap.find(flag);
  if (i != this->FlagMap.cend() && i->second.size() == 1) {
    return i->second[0].c_str();
  }
  return nullptr;
}
