/*
  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(element);
    } else {
      return false;
    }
  } else {
    /* Replacement was not provided so return all capturing groups except the group zero. */
    StringVector captures;
    if (capture(subject, captures)) {
      if (captures.size() == 1) {
        result.push_back(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;
  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 < matchCount; i++) {
    std::string_view capture = matches[i];
    String           dst(capture.data(), capture.length());

    CacheKeyDebug("capturing '%s' %d", dst.c_str(), i);
    result.push_back(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;
  int          matchCount = _re.exec(subject, matches, RE_NOTEMPTY);
  if (matchCount < 0) {
    if (matchCount != RE_ERROR_NOMATCH) {
      CacheKeyError("matching error %d", matchCount);
    }
    return false;
  }

  /* Verify the replacement has the right number of matching groups */
  for (int i = 0; i < _tokenCount; i++) {
    if (_tokens[i] >= matchCount) {
      CacheKeyError("invalid reference in replacement string: $%d", _tokens[i]);
      return false;
    }
  }

  int previous = 0;
  for (int i = 0; i < _tokenCount; i++) {
    int              replIndex = _tokens[i];
    std::string_view capture   = matches[replIndex];

    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;
  }

  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++;
      }
    }
  }

  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));
}
