/*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

/**
 * @file pattern.cc
 * @brief Regex related classes.
 * @see pattern.h
 */

#include "pattern.h"

static void
replaceString(String &str, const String &from, const String &to)
{
  if (from.empty()) {
    return;
  }

  String::size_type start_pos = 0;
  while ((start_pos = str.find(from, start_pos)) != String::npos) {
    str.replace(start_pos, from.length(), to);
    start_pos += to.length();
  }
}

Pattern::Pattern() : _pattern(""), _replacement("") {}

/**
 * @brief Initializes Regex pattern by providing the subject and replacement strings.
 * @param pattern Regex pattern, a string containing regex patterns, capturing groups.
 * @param replacement Regex replacement, a string where $0 ... $9 will be replaced with the corresponding capturing groups
 * @return true if successful, false if failure
 */
bool
Pattern::init(const String &pattern, const String &replacement, bool replace)
{
  _pattern.assign(pattern);
  _replacement.assign(replacement);
  _replace = replace;

  _tokenCount = 0;

  if (!compile()) {
    CacheKeyDebug("failed to initialize pattern:'%s', replacement:'%s'", pattern.c_str(), replacement.c_str());
    return false;
  }

  return true;
}

/**
 * @brief Initializes Regex pattern by providing the pattern only or pattern+replacement in a single configuration string.
 * @see init()
 * @param config Regex pattern <pattern> or Regex pattern + replacement in format /<pattern>/<replacement>/
 * @return true if successful, false if failure
 */
bool
Pattern::init(const String &config)
{
  if (config[0] == '/') {
    /* This is a config in format /regex/replacement/ */
    String pattern;
    String replacement;

    size_t start   = 1;
    size_t current = 0;
    size_t next    = 1;
    do {
      current = next + 1;
      next    = config.find_first_of('/', current);
    } while (next != String::npos && '\\' == config[next - 1]);

    if (next != String::npos) {
      pattern = config.substr(start, next - start);
    } else {
      /* Error, no closing '/' */
      CacheKeyError("failed to parse the pattern in '%s'", config.c_str());
      return false;
    }

    start = next + 1;
    do {
      current = next + 1;
      next    = config.find_first_of('/', current);
    } while (next != String::npos && '\\' == config[next - 1]);

    if (next != String::npos) {
      replacement = config.substr(start, next - start);
    } else {
      /* Error, no closing '/' */
      CacheKeyError("failed to parse the replacement in '%s'", config.c_str());
      return false;
    }

    // Remove '\' which escaped '/' inside the pattern and replacement strings.
    ::replaceString(pattern, "\\/", "/");
    ::replaceString(replacement, "\\/", "/");

    return this->init(pattern, replacement, /* replace */ true);
  } else {
    return this->init(config, /* replacement */ "", /*replace */ false);
  }

  /* Should never get here. */
  return false;
}

/**
 * @brief Checks if the pattern object was initialized with a meaningful regex pattern.
 * @return true if initialized, false if not.
 */
bool
Pattern::empty() const
{
  return _pattern.empty() || _re.empty();
}

/**
 * @brief Capture or capture-and-replace depending on whether a replacement string is specified.
 * @see replace()
 * @see capture()
 * @param subject PCRE2 subject string
 * @param result vector of strings where the result of captures or the replacements will be returned.
 * @return true if there was a match and capture or replacement succeeded, false if failure.
 */
bool
Pattern::process(const String &subject, StringVector &result)
{
  if (_replace) {
    /* Replacement pattern was provided in the configuration - capture and replace. */
    String element;
    if (replace(subject, element)) {
      result.push_back(std::move(element));
    } else {
      return false;
    }
  } else {
    /* Replacement was not provided so return all capturing groups except the group zero. */
    StringVector captures;
    if (capture(subject, captures) && !captures.empty()) {
      if (captures.size() == 1) {
        result.push_back(std::move(captures[0]));
      } else {
        StringVector::iterator it = captures.begin() + 1;
        for (; it != captures.end(); it++) {
          result.push_back(*it);
        }
      }
    } else {
      return false;
    }
  }

  return true;
}

/**
 * @brief Regex matches a subject string against the regex pattern.
 * @param subject Regex subject
 * @return true - matched, false - did not.
 */
bool
Pattern::match(const String &subject)
{
  CacheKeyDebug("matching '%s' to '%s'", _pattern.c_str(), subject.c_str());

  if (_re.empty()) {
    return false;
  }

  RegexMatches matches;
  int          matchCount = _re.exec(subject, matches, RE_NOTEMPTY);
  if (matchCount < 0) {
    if (matchCount != RE_ERROR_NOMATCH) {
      CacheKeyError("matching error %d", matchCount);
    }
    return false;
  }

  return true;
}

/**
 * @brief Return all Regex capture groups that matched in the subject string
 * @param subject Regex subject string
 * @param result reference to vector of strings containing all capture groups
 */
bool
Pattern::capture(const String &subject, StringVector &result)
{
  CacheKeyDebug("capturing '%s' from '%s'", _pattern.c_str(), subject.c_str());

  if (_re.empty()) {
    CacheKeyError("regular expression not initialized");
    return false;
  }

  RegexMatches matches(_captureCount + 1);
  int          matchCount = _re.exec(subject, matches, RE_NOTEMPTY);
  if (matchCount < 0) {
    if (matchCount != RE_ERROR_NOMATCH) {
      CacheKeyError("matching error %d", matchCount);
    }
    return false;
  }

  for (int i = 0; i < matches.size(); i++) {
    std::string_view capture = matches[i];
    String           dst(capture.data(), capture.length());

    CacheKeyDebug("capturing '%s' %d", dst.c_str(), i);
    result.push_back(std::move(dst));
  }

  return true;
}

/**
 * @brief Replaces all replacements found in the replacement string with what matched in the Regex capturing groups.
 * @param subject Regex subject string
 * @param result reference to A string where the result of the replacement will be stored
 * @return true - success, false - nothing matched or failure.
 */
bool
Pattern::replace(const String &subject, String &result)
{
  CacheKeyDebug("replacing:'%s' in pattern:'%s', subject:'%s'", _replacement.c_str(), _pattern.c_str(), subject.c_str());

  if (_re.empty() || !_replace) {
    CacheKeyError("regular expression not initialized or not configured to replace");
    return false;
  }

  RegexMatches matches(_captureCount + 1);
  int          matchCount = _re.exec(subject, matches, RE_NOTEMPTY);
  if (matchCount < 0) {
    if (matchCount != RE_ERROR_NOMATCH) {
      CacheKeyError("matching error %d", matchCount);
    }
    return false;
  }

  int previous = 0;
  for (int i = 0; i < _tokenCount; i++) {
    int replIndex = _tokens[i];
    // Trailing optional groups may not participate in this match.
    std::string_view capture = (replIndex < matches.size()) ? matches[replIndex] : std::string_view{""};

    String src(_replacement, _tokenOffset[i], 2);
    String dst(capture.data(), capture.length());

    CacheKeyDebug("replacing '%s' with '%s'", src.c_str(), dst.c_str());

    result.append(_replacement, previous, _tokenOffset[i] - previous);
    result.append(dst);

    previous = _tokenOffset[i] + 2; /* 2 is the size of $0 or $1 or $2, ... or $9 */
  }

  result.append(_replacement, previous, _replacement.length() - previous);

  CacheKeyDebug("replacing '%s' resulted in '%s'", _replacement.c_str(), result.c_str());

  return true;
}

/**
 * @brief Compiles the regex, called only during initialization.
 * @return true if successful, false if not.
 */
bool
Pattern::compile()
{
  std::string error;
  int         errOffset;

  CacheKeyDebug("compiling pattern:'%s', replace: %s, replacement:'%s'", _pattern.c_str(), _replace ? "true" : "false",
                _replacement.c_str());

  if (!_re.compile(_pattern, error, errOffset)) {
    CacheKeyError("compile of regex '%s' at char %d: %s", _pattern.c_str(), errOffset, error.c_str());
    return false;
  }

  _captureCount = _re.get_capture_count();
  if (_captureCount < 0) {
    CacheKeyError("failed to get capture count for pattern '%s'", _pattern.c_str());
    return false;
  }

  if (!_replace) {
    /* No replacement necessary - we are done. */
    return true;
  }

  _tokenCount  = 0;
  bool success = true;

  for (unsigned i = 0; i < _replacement.length(); i++) {
    if (_replacement[i] == '$') {
      if (_tokenCount >= TOKENCOUNT) {
        CacheKeyError("too many tokens in replacement string: %s", _replacement.c_str());

        success = false;
        break;
      } else if (_replacement[i + 1] < '0' || _replacement[i + 1] > '9') {
        CacheKeyError("invalid replacement token $%c in %s: should be $0 - $9", _replacement[i + 1], _replacement.c_str());

        success = false;
        break;
      } else {
        /* Store the location of the replacement */
        /* Convert '0' to 0 */
        _tokens[_tokenCount]      = _replacement[i + 1] - '0';
        _tokenOffset[_tokenCount] = i;
        _tokenCount++;
        /* Skip the next char */
        i++;
      }
    }
  }

  if (success) {
    for (int i = 0; i < _tokenCount; i++) {
      if (_tokens[i] > _captureCount) {
        CacheKeyError("invalid reference $%d in replacement '%s': pattern defines only %d group(s)", _tokens[i],
                      _replacement.c_str(), _captureCount);
        return false;
      }
    }
  }

  return success;
}

/**
 * @brief Destructor, deletes all patterns.
 */
MultiPattern::~MultiPattern() {}

/**
 * @brief Check if empty.
 * @return true if the classification contains any patterns, false otherwise
 */
bool
MultiPattern::empty() const
{
  return _list.empty();
}

/**
 * @brief Adds a pattern to the multi-pattern
 *
 * The order of addition matters during the classification
 * @param pattern pattern pointer
 */
void
MultiPattern::add(std::unique_ptr<Pattern> pattern)
{
  this->_list.push_back(std::move(pattern));
}

/**
 * @brief Matches the subject string against all patterns.
 * @param subject subject string.
 * @return true if any matches, false if nothing matches.
 */
bool
MultiPattern::match(const String &subject) const
{
  for (auto &p : this->_list) {
    if (nullptr != p && p->match(subject)) {
      return true;
    }
  }
  return false;
}

/**
 * @brief Returns the name of the multi-pattern (set during the instantiation only).
 */
const String &
MultiPattern::name() const
{
  return _name;
}

bool
MultiPattern::process(const String &subject, StringVector &result) const
{
  bool res = false;
  for (auto &p : this->_list) {
    if (nullptr != p && p->process(subject, result)) {
      res = true;
    }
  }
  return res;
}

/**
 * @brief Destructor, deletes all multi-patterns.
 */
Classifier::~Classifier() {}

/**
 * @brief Classifies a subject string by matching against the vector of named multi-patterns
 * in the order they were added and returns the first matching multi-pattern name.
 * @param subject string subject being classified.
 * @param name reference to a string where the name of the class that matched first will be stored.
 * @return true if something matched, false otherwise.
 */
bool
Classifier::classify(const String &subject, String &name) const
{
  bool matched = false;
  for (auto &p : _list) {
    if (p->empty()) {
      continue;
    } else if (p->match(subject)) {
      name    = p->name();
      matched = true;
      break;
    }
  }
  return matched;
}

/**
 * @brief Adds a multi-pattern to the classifier.
 *
 * The order of addition matters during the classification
 * @param pattern multi-pattern pointer
 */
void
Classifier::add(std::unique_ptr<MultiPattern> pattern)
{
  _list.push_back(std::move(pattern));
}
