#include "torlinkc/util/url_encode.hpp"

#include <cctype>

namespace torlinkc {

namespace {
bool isUnreserved(unsigned char c) {
  return std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' ||
         c == '(' || c == ')';
}
}  // namespace

std::string encodeURIComponent(const std::string& s) {
  std::string out;
  out.reserve(s.size());
  static const char* hex = "0123456789ABCDEF";
  for (unsigned char c : s) {
    if (isUnreserved(c)) {
      out += static_cast<char>(c);
    } else {
      out += '%';
      out += hex[c >> 4];
      out += hex[c & 0xF];
    }
  }
  return out;
}

std::string decodeURIComponent(const std::string& s) {
  std::string out;
  out.reserve(s.size());
  for (std::size_t i = 0; i < s.size(); ++i) {
    if (s[i] == '+') {
      out += ' ';
    } else if (s[i] == '%' && i + 2 < s.size() && std::isxdigit(static_cast<unsigned char>(s[i + 1])) &&
               std::isxdigit(static_cast<unsigned char>(s[i + 2]))) {
      out += static_cast<char>(std::stoi(s.substr(i + 1, 2), nullptr, 16));
      i += 2;
    } else {
      out += s[i];
    }
  }
  return out;
}

}  // namespace torlinkc
