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

#include "cmConfigure.h" // IWYU pragma: keep

#include <cctype>
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <numeric>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <cm/string_view>

#include "cmRange.h"
#include "cmValue.h"

/** String range type.  */
using cmStringRange = cmRange<std::vector<std::string>::const_iterator>;

/** Returns length of a literal string.  */
template <size_t N>
constexpr size_t cmStrLen(char const (&)[N])
{
  return N - 1;
}

/** Callable string comparison struct.  */
struct cmStrCmp
{
  cmStrCmp(std::string str)
    : Test_(std::move(str))
  {
  }

  bool operator()(cm::string_view sv) const { return this->Test_ == sv; }

private:
  std::string const Test_;
};

/**
 * Test if two strings are identical, ignoring case.
 *
 * Note that this is not guaranteed to work correctly on non-ASCII strings.
 */
bool cmStrCaseEq(cm::string_view a, cm::string_view b);

/** Returns true if the character @a ch is a whitespace character.  **/
inline bool cmIsSpace(char ch)
{
  // isspace takes 'int' but documents that the value must be representable
  // by 'unsigned char', or be EOF.  Cast to 'unsigned char' to avoid sign
  // extension while converting to 'int'.
  return std::isspace(static_cast<unsigned char>(ch));
}

/** Returns a string that has whitespace removed from the start and the end. */
std::string cmTrimWhitespace(cm::string_view str);

/**
 * Returns a string view that has whitespace removed from the start and the
 * end.
 */
cm::string_view cmStripWhitespace(cm::string_view str);

/** Returns a string that has quotes removed from the start and the end. */
std::string cmRemoveQuotes(cm::string_view str);

/** Escape quotes in a string.  */
std::string cmEscapeQuotes(cm::string_view str);

/** Joins elements of a range with separator into a single string.  */
template <typename Range>
std::string cmJoin(Range const& rng, cm::string_view separator)
{
  if (rng.empty()) {
    return std::string();
  }

  std::ostringstream os;
  auto it = rng.begin();
  auto const end = rng.end();
  os << *it;
  while (++it != end) {
    os << separator << *it;
  }
  return os.str();
}

/** Generic function to join strings range with separator
 *  and initial leading string into a single string.
 */
template <typename Range>
std::string cmJoinStrings(Range const& rng, cm::string_view separator,
                          cm::string_view initial)
{
  if (rng.empty()) {
    return { std::begin(initial), std::end(initial) };
  }

  std::string result;
  result.reserve(std::accumulate(
    std::begin(rng), std::end(rng),
    initial.size() + (rng.size() - 1) * separator.size(),
    [](std::size_t sum, typename Range::value_type const& item) {
      return sum + item.size();
    }));
  result.append(std::begin(initial), std::end(initial));

  auto begin = std::begin(rng);
  auto end = std::end(rng);
  result += *begin;

  for (++begin; begin != end; ++begin) {
    result.append(std::begin(separator), std::end(separator));
    result += *begin;
  }

  return result;
}

/**
 * Faster overloads for std::string ranges.
 * If @a initial is provided, it prepends the resulted string without
 * @a separator between them.
 */
std::string cmJoin(std::vector<std::string> const& rng,
                   cm::string_view separator, cm::string_view initial = {});

std::string cmJoin(cmStringRange rng, cm::string_view separator,
                   cm::string_view initial = {});

enum class cmTokenizerMode
{
  /// A backward-compatible behavior when in the case of no
  /// tokens have found in an input text it'll return one empty
  /// token in the result container (vector).
  Legacy,
  /// The new behavior is to return an empty vector.
  New
};

/**
 * \brief A generic version of a tokenizer.
 *
 * Extract tokens from the input string separated by any
 * of the characters in `sep` and assign them to the
 * given output iterator.
 *
 * The `mode` parameter defines the behavior in the case when
 * no tokens have found in the input text.
 *
 */
template <typename StringT, typename OutIt, typename Sep = char>
void cmTokenize(OutIt outIt, cm::string_view str, Sep sep,
                cmTokenizerMode mode)
{
  auto hasTokens = false;
  // clang-format off
  for (auto start = str.find_first_not_of(sep)
    , end = str.find_first_of(sep, start)
    ; start != cm::string_view::npos
    ; start = str.find_first_not_of(sep, end)
    , end = str.find_first_of(sep, start)
    , hasTokens = true
    ) {
    *outIt++ = StringT{ str.substr(start, end - start) };
  }
  // clang-format on
  if (!hasTokens && mode == cmTokenizerMode::Legacy) {
    *outIt = StringT{};
  }
}

/**
 * \brief Extract tokens that are separated by any of the
 * characters in `sep`.
 *
 * Backward compatible signature.
 *
 * \return A vector of strings.
 */
template <typename Sep = char>
std::vector<std::string> cmTokenize(
  cm::string_view str, Sep sep, cmTokenizerMode mode = cmTokenizerMode::Legacy)
{
  using StringType = std::string;
  std::vector<StringType> tokens;
  cmTokenize<StringType>(std::back_inserter(tokens), str, sep, mode);
  return tokens;
}

/**
 * \brief Extract tokens that are separated by any of the
 * characters in `sep`.
 *
 * \return A vector of string views.
 */
template <typename Sep = char>
std::vector<cm::string_view> cmTokenizedView(
  cm::string_view str, Sep sep, cmTokenizerMode mode = cmTokenizerMode::Legacy)
{
  using StringType = cm::string_view;
  std::vector<StringType> tokens;
  cmTokenize<StringType>(std::back_inserter(tokens), str, sep, mode);
  return tokens;
}

/** Concatenate string pieces into a single string.  */
std::string cmCatViews(
  std::initializer_list<std::pair<cm::string_view, std::string*>> views);

/** Utility class for cmStrCat.  */
class cmAlphaNum
{
public:
  cmAlphaNum(cm::string_view view)
    : View_(view)
  {
  }
  cmAlphaNum(std::string const& str)
    : View_(str)
  {
  }
  cmAlphaNum(std::string&& str)
    : RValueString_(&str)
  {
  }
  cmAlphaNum(char const* str)
    : View_(str ? cm::string_view(str) : cm::string_view())
  {
  }
  cmAlphaNum(char ch)
    : View_(this->Digits_, 1)
  {
    this->Digits_[0] = ch;
  }
  cmAlphaNum(int val);
  cmAlphaNum(unsigned int val);
  cmAlphaNum(long int val);
  cmAlphaNum(unsigned long int val);
  cmAlphaNum(long long int val);
  cmAlphaNum(unsigned long long int val);
  cmAlphaNum(float val);
  cmAlphaNum(double val);
  cmAlphaNum(cmValue value)
    : View_(*value)
  {
  }

  cm::string_view View() const
  {
    if (this->RValueString_) {
      return *this->RValueString_;
    }
    return this->View_;
  }

  std::string* RValueString() const { return this->RValueString_; }

private:
  std::string* RValueString_ = nullptr;
  cm::string_view View_;
  char Digits_[32];
};

/** Concatenate string pieces and numbers into a single string.  */
template <typename A, typename B, typename... AV>
inline std::string cmStrCat(A&& a, B&& b, AV&&... args)
{
  static auto const makePair =
    [](cmAlphaNum const& arg) -> std::pair<cm::string_view, std::string*> {
    return { arg.View(), arg.RValueString() };
  };

  return cmCatViews({ makePair(std::forward<A>(a)),
                      makePair(std::forward<B>(b)),
                      makePair(std::forward<AV>(args))... });
}

/** Joins wrapped elements of a range with separator into a single string.  */
template <typename Range>
std::string cmWrap(cm::string_view prefix, Range const& rng,
                   cm::string_view suffix, cm::string_view sep)
{
  if (rng.empty()) {
    return std::string();
  }
  return cmCatViews({ { prefix, nullptr },
                      { cmJoin(rng,
                               cmCatViews({ { suffix, nullptr },
                                            { sep, nullptr },
                                            { prefix, nullptr } })),
                        nullptr },
                      { suffix, nullptr } });
}

/** Joins wrapped elements of a range with separator into a single string.  */
template <typename Range>
std::string cmWrap(char prefix, Range const& rng, char suffix,
                   cm::string_view sep)
{
  return cmWrap(cm::string_view(&prefix, 1), rng, cm::string_view(&suffix, 1),
                sep);
}

/** Returns true if string @a str starts with the character @a prefix.  */
inline bool cmHasPrefix(cm::string_view str, char prefix)
{
  return !str.empty() && (str.front() == prefix);
}

/** Returns true if string @a str starts with string @a prefix.  */
inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix)
{
  return str.compare(0, prefix.size(), prefix) == 0;
}

/** Returns true if string @a str starts with string @a prefix.  */
inline bool cmHasPrefix(cm::string_view str, cmValue prefix)
{
  if (!prefix) {
    return false;
  }

  return str.compare(0, prefix->size(), *prefix) == 0;
}

/** Returns true if string @a str starts with string @a prefix.  */
template <size_t N>
inline bool cmHasLiteralPrefix(cm::string_view str, char const (&prefix)[N])
{
  return cmHasPrefix(str, cm::string_view(prefix, N - 1));
}

/** Returns true if string @a str ends with the character @a suffix.  */
inline bool cmHasSuffix(cm::string_view str, char suffix)
{
  return !str.empty() && (str.back() == suffix);
}

/** Returns true if string @a str ends with string @a suffix.  */
inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix)
{
  return str.size() >= suffix.size() &&
    str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

/** Returns true if string @a str ends with string @a suffix.  */
inline bool cmHasSuffix(cm::string_view str, cmValue suffix)
{
  if (!suffix) {
    return false;
  }

  return str.size() >= suffix->size() &&
    str.compare(str.size() - suffix->size(), suffix->size(), *suffix) == 0;
}

/** Returns true if string @a str ends with string @a suffix.  */
template <size_t N>
inline bool cmHasLiteralSuffix(cm::string_view str, char const (&suffix)[N])
{
  return cmHasSuffix(str, cm::string_view(suffix, N - 1));
}

/** Removes an existing suffix character of from the string @a str.  */
inline void cmStripSuffixIfExists(std::string& str, char suffix)
{
  if (cmHasSuffix(str, suffix)) {
    str.pop_back();
  }
}

/** Removes an existing suffix string of from the string @a str.  */
inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix)
{
  if (cmHasSuffix(str, suffix)) {
    str.resize(str.size() - suffix.size());
  }
}

/** Converts a string to long. Expects that the whole string is an integer.  */
bool cmStrToLong(char const* str, long* value);
bool cmStrToLong(std::string const& str, long* value);

/** Converts a string to unsigned long. Expects that the whole string is an
 * integer */
bool cmStrToULong(char const* str, unsigned long* value);
bool cmStrToULong(std::string const& str, unsigned long* value);

/** Converts a string to long long. Expects that the whole string
 * is an integer */
bool cmStrToLongLong(char const* str, long long* value);
bool cmStrToLongLong(std::string const& str, long long* value);

/** Converts a string to unsigned long long. Expects that the whole string
 * is an integer */
bool cmStrToULongLong(char const* str, unsigned long long* value);
bool cmStrToULongLong(std::string const& str, unsigned long long* value);
