#ifndef THIRD_PARTY_GBMCWEB_HTTP_ROUTING_H_
#define THIRD_PARTY_GBMCWEB_HTTP_ROUTING_H_

#ifdef BMCWEB_ENABLE_GRPC
#include "absl/log/log.h"
#include "authorizer_enums.h"
#include "bmcweb_authorizer_singleton.h"
#endif

#include <algorithm>
#include <array>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <initializer_list>
#include <limits>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "boost/beast/ssl/ssl_stream.hpp"  // NOLINT
#include "boost/container/flat_map.hpp"  // NOLINT
#include "common.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "verb.hpp"
#include "websocket.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "privileges.hpp"
// TODO(haoooamazing): Remove dbus_utils.h include once indirect include is
// fixed for redfish-core/lib/ethernet.hpp
#include "dbus_utils.hpp"  // NOLINT(misc-include-cleaner)
#include "managed_store.hpp"

namespace crow {

class BaseRule {
 public:
  explicit BaseRule(std::string_view thisRule) : rule(thisRule) {}

  virtual ~BaseRule() = default;

  BaseRule(const BaseRule&) = delete;
  BaseRule(BaseRule&&) = delete;
  BaseRule& operator=(const BaseRule&) = delete;
  BaseRule& operator=(const BaseRule&&) = delete;

  virtual void validate() = 0;
  std::unique_ptr<BaseRule> upgrade() {
    if (ruleToUpgrade) {
      return std::move(ruleToUpgrade);
    }
    return {};
  }

  virtual void handle(const Request& /*req*/,
                      const std::shared_ptr<bmcweb::AsyncResp>&,
                      const RoutingParams&) = 0;
#ifndef BMCWEB_ENABLE_SSL
  virtual void handleUpgrade(
      const Request& /*req*/,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      boost::asio::ip::tcp::socket&& /*adaptor*/) {
    asyncResp->res.result(boost::beast::http::status::not_found);
  }
#else
  virtual void handleUpgrade(
      const Request& /*req*/,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&& /*adaptor*/) {
    asyncResp->res.result(boost::beast::http::status::not_found);
  }
#endif

  size_t getMethods() const { return methodsBitfield; }

  bool checkPrivileges(const redfish::Privileges& userPrivileges) {
    // If there are no privileges assigned, assume no privileges
    // required
    if (privilegesSet.empty()) {
      return true;
    }

    // NOLINTNEXTLINE(readability-use_anyofallof)
    for (const redfish::Privileges& requiredPrivileges : privilegesSet) {
      if (userPrivileges.isSupersetOf(requiredPrivileges)) {
        return true;
      }
    }
    return false;
  }

  size_t methodsBitfield{1 << static_cast<size_t>(HttpVerb::Get)};  // NOLINT
  static_assert(std::numeric_limits<decltype(methodsBitfield)>::digits >
                    methodNotAllowedIndex,
                "Not enough bits to store bitfield");

  std::vector<redfish::Privileges> privilegesSet;  // NOLINT

  std::string rule;     // NOLINT
  std::string nameStr;  // NOLINT

  std::unique_ptr<BaseRule> ruleToUpgrade;  // NOLINT

  friend class Router;
  template <typename T>
  friend struct RuleParameterTraits;
};

namespace detail {
namespace routing_handler_call_helper {
template <typename T, int Pos>
struct CallPair {
  using type = T;
  static const int pos = Pos;
};

template <typename H1>
struct CallParams {
  H1& handler;
  const RoutingParams& params;
  const Request& req;
  const std::shared_ptr<bmcweb::AsyncResp>& asyncResp;  // NOLINT
};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename S1, typename S2>
struct Call {};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename... Args1, typename... Args2>
struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>,
            black_magic::S<Args2...>> {
  void operator()(F cparams) {
    using pushed = typename black_magic::S<Args2...>::template push_back<
        CallPair<int64_t, NInt>>;
    Call<F, NInt + 1, NUint, NDouble, NString, black_magic::S<Args1...>,
         pushed>()(cparams);
  }
};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename... Args1, typename... Args2>
struct Call<F, NInt, NUint, NDouble, NString,
            black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>> {
  void operator()(F cparams) {
    using pushed = typename black_magic::S<Args2...>::template push_back<
        CallPair<uint64_t, NUint>>;
    Call<F, NInt, NUint + 1, NDouble, NString, black_magic::S<Args1...>,
         pushed>()(cparams);
  }
};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename... Args1, typename... Args2>
struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>,
            black_magic::S<Args2...>> {
  void operator()(F cparams) {
    using pushed = typename black_magic::S<Args2...>::template push_back<
        CallPair<double, NDouble>>;
    Call<F, NInt, NUint, NDouble + 1, NString, black_magic::S<Args1...>,
         pushed>()(cparams);
  }
};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename... Args1, typename... Args2>
struct Call<F, NInt, NUint, NDouble, NString,
            black_magic::S<std::string, Args1...>, black_magic::S<Args2...>> {
  void operator()(F cparams) {
    using pushed = typename black_magic::S<Args2...>::template push_back<
        CallPair<std::string, NString>>;
    Call<F, NInt, NUint, NDouble, NString + 1, black_magic::S<Args1...>,
         pushed>()(cparams);
  }
};

template <typename F, int NInt, int NUint, int NDouble, int NString,
          typename... Args1>
struct Call<F, NInt, NUint, NDouble, NString, black_magic::S<>,
            black_magic::S<Args1...>> {
  void operator()(F cparams) {
    cparams.handler(
        cparams.req, cparams.asyncResp,
        cparams.params.template get<typename Args1::type>(Args1::pos)...);
  }
};

template <typename Func, typename... ArgsWrapped>
struct Wrapped {
  template <typename... Args>
  void set(
      Func f,
      typename std::enable_if<
          !std::is_same<
              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
              const Request&>::value,
          int>::type /*enable*/
      = 0) {
    handler = [f = std::forward<Func>(f)](
                  const Request&,
                  const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                  Args... args) { asyncResp->res.result(f(args...)); };
  }

  template <typename Req, typename... Args>
  struct ReqHandlerWrapper {
    explicit ReqHandlerWrapper(Func fIn) : f(std::move(fIn)) {}

    void operator()(const Request& req,
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                    Args... args) {
      asyncResp->res.result(f(req, args...));
    }

    Func f;
  };

  template <typename... Args>
  void set(
      Func f,
      typename std::enable_if<
          std::is_same<
              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
              const Request&>::value &&
              !std::is_same<typename std::tuple_element<
                                1, std::tuple<Args..., void, void>>::type,
                            const std::shared_ptr<bmcweb::AsyncResp>&>::value,
          int>::type /*enable*/
      = 0) {
    handler = ReqHandlerWrapper<Args...>(std::move(f));
    /*handler = (
        [f = std::move(f)]
        (const Request& req, Response& res, Args... args){
             res.result(f(req, args...));
             res.end();
        });*/
  }

  template <typename... Args>
  void set(
      Func f,
      typename std::enable_if<
          std::is_same<
              typename std::tuple_element<0, std::tuple<Args..., void>>::type,
              const Request&>::value &&
              std::is_same<typename std::tuple_element<
                               1, std::tuple<Args..., void, void>>::type,
                           const std::shared_ptr<bmcweb::AsyncResp>&>::value,
          int>::type /*enable*/
      = 0) {
    handler = std::move(f);
  }

  template <typename... Args>
  struct HandlerTypeHelper {
    using type =
        std::function<void(const crow::Request& /*req*/,
                           const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>;
    using args_type = black_magic::S<typename black_magic::PromoteT<Args>...>;
  };

  template <typename... Args>
  struct HandlerTypeHelper<const Request&, Args...> {
    using type =
        std::function<void(const crow::Request& /*req*/,
                           const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>;
    using args_type = black_magic::S<typename black_magic::PromoteT<Args>...>;
  };

  template <typename... Args>
  struct HandlerTypeHelper<const Request&,
                           const std::shared_ptr<bmcweb::AsyncResp>&, Args...> {
    using type =
        std::function<void(const crow::Request& /*req*/,
                           const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>;
    using args_type = black_magic::S<typename black_magic::PromoteT<Args>...>;
  };

  typename HandlerTypeHelper<ArgsWrapped...>::type handler;

  void operator()(const Request& req,
                  const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                  const RoutingParams& params) {
    detail::routing_handler_call_helper::Call<
        detail::routing_handler_call_helper::CallParams<decltype(handler)>, 0,
        0, 0, 0, typename HandlerTypeHelper<ArgsWrapped...>::args_type,
        black_magic::S<>>()(
        detail::routing_handler_call_helper::CallParams<decltype(handler)>{
            handler, params, req, asyncResp});
  }
};
}  // namespace routing_handler_call_helper
}  // namespace detail

class WebSocketRule : public BaseRule {
  using self_t = WebSocketRule;

 public:
  explicit WebSocketRule(const std::string& ruleIn) : BaseRule(ruleIn) {}

  void validate() override {}

  void handle(const Request& /*req*/,
              const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
              const RoutingParams& /*params*/) override {
    asyncResp->res.result(boost::beast::http::status::not_found);
  }

#ifndef BMCWEB_ENABLE_SSL
  void handleUpgrade(const Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/,
                     boost::asio::ip::tcp::socket&& adaptor) override {
    BMCWEB_LOG_DEBUG << "Websocket handles upgrade";
    std::shared_ptr<
        crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>>
        myConnection = std::make_shared<
            crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>>(
            req, std::move(adaptor), openHandler, messageHandler,
            messageExHandler, closeHandler, errorHandler);
    myConnection->start();
  }
#else
  void handleUpgrade(const Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& /*asyncResp*/,
                     boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&
                         adaptor) override {
    BMCWEB_LOG_DEBUG << "Websocket handles upgrade";
    std::shared_ptr<crow::websocket::ConnectionImpl<
        boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>
        myConnection = std::make_shared<crow::websocket::ConnectionImpl<
            boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>(
            req, std::move(adaptor), openHandler, messageHandler,
            messageExHandler, closeHandler, errorHandler);
    myConnection->start();
  }
#endif

  template <typename Func>
  self_t& onopen(Func f) {
    openHandler = f;
    return *this;
  }

  template <typename Func>
  self_t& onmessage(Func f) {
    messageHandler = f;
    return *this;
  }

  template <typename Func>
  self_t& onmessageex(Func f) {
    messageExHandler = f;
    return *this;
  }

  template <typename Func>
  self_t& onclose(Func f) {
    closeHandler = f;
    return *this;
  }

  template <typename Func>
  self_t& onerror(Func f) {
    errorHandler = f;
    return *this;
  }

 protected:
  std::function<void(crow::websocket::Connection&)> openHandler;  // NOLINT
  std::function<void(crow::websocket::Connection&, const std::string&, bool)>
      messageHandler;  // NOLINT
  std::function<void(crow::websocket::Connection&, std::string_view,
                     crow::websocket::MessageType type,
                     std::function<void()>&& whenComplete)>
      messageExHandler;  // NOLINT
  std::function<void(crow::websocket::Connection&, const std::string&)>
      closeHandler;                                                // NOLINT
  std::function<void(crow::websocket::Connection&)> errorHandler;  // NOLINT
};

template <typename T>
struct RuleParameterTraits {
  using self_t = T;
  WebSocketRule& websocket() {
    self_t* self = static_cast<self_t*>(this);
    WebSocketRule* p = new WebSocketRule(self->rule);
    self->ruleToUpgrade.reset(p);
    return *p;
  }

  self_t& name(std::string_view name) noexcept {
    self_t* self = static_cast<self_t*>(this);
    self->nameStr = name;
    return *self;
  }

  self_t& methods(boost::beast::http::verb method) {
    self_t* self = static_cast<self_t*>(this);
    std::optional<HttpVerb> verb = httpVerbFromBoost(method);
    if (verb) {
      self->methodsBitfield = 1U << static_cast<size_t>(*verb);
    }
    return *self;
  }

  template <typename... MethodArgs>
  self_t& methods(boost::beast::http::verb method, MethodArgs... argsMethod) {
    self_t* self = static_cast<self_t*>(this);
    methods(argsMethod...);
    std::optional<HttpVerb> verb = httpVerbFromBoost(method);
    if (verb) {
      self->methodsBitfield |= 1U << static_cast<size_t>(*verb);
    }
    return *self;
  }

  self_t& notFound() {
    self_t* self = static_cast<self_t*>(this);
    self->methodsBitfield = 1U << notFoundIndex;
    return *self;
  }

  self_t& methodNotAllowed() {
    self_t* self = static_cast<self_t*>(this);
    self->methodsBitfield = 1U << methodNotAllowedIndex;
    return *self;
  }

  self_t& privileges(
      const std::initializer_list<std::initializer_list<const char*>>& p) {
    self_t* self = static_cast<self_t*>(this);
    for (const std::initializer_list<const char*>& privilege : p) {
      self->privilegesSet.emplace_back(privilege);
    }
    return *self;
  }

  template <size_t N, typename... MethodArgs>
  self_t& privileges(const std::array<redfish::Privileges, N>& p) {
    self_t* self = static_cast<self_t*>(this);
    for (const redfish::Privileges& privilege : p) {
      self->privilegesSet.emplace_back(privilege);
    }
    return *self;
  }
};

class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule> {
 public:
  explicit DynamicRule(const std::string& ruleIn) : BaseRule(ruleIn) {}

  void validate() override {
    if (!erasedHandler) {
      throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
                               "no handler for url " + rule);
    }
  }

  void handle(const Request& req,
              const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
              const RoutingParams& params) override {
    erasedHandler(req, asyncResp, params);
  }

  template <typename Func>
  void operator()(Func f) {
    using boost::callable_traits::args_t;
    constexpr size_t arity = std::tuple_size<args_t<Func>>::value;
    constexpr auto is = std::make_integer_sequence<unsigned, arity>{};
    erasedHandler = wrap(std::move(f), is);
  }

  // enable_if Arg1 == request && Arg2 == Response
  // enable_if Arg1 == request && Arg2 != response
  // enable_if Arg1 != request

  template <typename Func, unsigned... Indices>
  std::function<void(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&,
                     const RoutingParams&)>
  wrap(Func f, std::integer_sequence<unsigned, Indices...> /*is*/) {
    using function_t = crow::utility::FunctionTraits<Func>;

    if (!black_magic::isParameterTagCompatible(
            black_magic::getParameterTag(rule),
            black_magic::computeParameterTagFromArgsList<
                typename function_t::template arg<Indices>...>::value)) {
      throw std::runtime_error(
          "routeDynamic: Handler type is mismatched "
          "with URL parameters: " +
          rule);
    }
    auto ret = detail::routing_handler_call_helper::Wrapped<
        Func, typename function_t::template arg<Indices>...>();
    ret.template set<typename function_t::template arg<Indices>...>(
        std::move(f));
    return ret;
  }

  template <typename Func>
  void operator()(std::string name, Func&& f) {
    nameStr = std::move(name);
    (*this).template operator()<Func>(std::forward(f));
  }

 private:
  std::function<void(const Request&, const std::shared_ptr<bmcweb::AsyncResp>&,
                     const RoutingParams&)>
      erasedHandler;  // NOLINT
};

template <typename... Args>
class TaggedRule : public BaseRule,
                   public RuleParameterTraits<TaggedRule<Args...>> {
 public:
  using self_t = TaggedRule<Args...>;

  explicit TaggedRule(std::string_view ruleIn) : BaseRule(ruleIn) {}

  void validate() override {
    if (!handler) {
      throw std::runtime_error(nameStr + (!nameStr.empty() ? ": " : "") +
                               "no handler for url " + rule);
    }
  }

  template <typename Func>
  typename std::enable_if<
      black_magic::CallHelper<Func, black_magic::S<Args...>>::value, void>::type
  operator()(Func&& f) {
    static_assert(
        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
            black_magic::CallHelper<
                Func, black_magic::S<crow::Request, Args...>>::value,
        "Handler type is mismatched with URL parameters");
    static_assert(
        !std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
        "Handler function cannot have void return type; valid return "
        "types: "
        "string, int, crow::response, nlohmann::json");

    handler = [f = std::forward<Func>(f)](
                  const Request&,
                  const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                  Args... args) { asyncResp->res.result(f(args...)); };
  }

  template <typename Func>
  typename std::enable_if<
      !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
          black_magic::CallHelper<
              Func, black_magic::S<crow::Request, Args...>>::value,
      void>::type
  operator()(Func&& f) {
    static_assert(
        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
            black_magic::CallHelper<
                Func, black_magic::S<crow::Request, Args...>>::value,
        "Handler type is mismatched with URL parameters");
    static_assert(
        !std::is_same<void, decltype(f(std::declval<crow::Request>(),
                                       std::declval<Args>()...))>::value,
        "Handler function cannot have void return type; valid return "
        "types: "
        "string, int, crow::response,nlohmann::json");

    handler = [f = std::forward<Func>(f)](
                  const crow::Request& req,
                  const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                  Args... args) { asyncResp->res.result(f(req, args...)); };
  }

  template <typename Func>
  typename std::enable_if<
      !black_magic::CallHelper<Func, black_magic::S<Args...>>::value &&
          !black_magic::CallHelper<
              Func, black_magic::S<crow::Request, Args...>>::value,
      void>::type
  operator()(Func&& f) {
    static_assert(
        black_magic::CallHelper<Func, black_magic::S<Args...>>::value ||
            black_magic::CallHelper<
                Func, black_magic::S<crow::Request, Args...>>::value ||
            black_magic::CallHelper<
                Func, black_magic::S<crow::Request,
                                     std::shared_ptr<bmcweb::AsyncResp>&,
                                     Args...>>::value,
        "Handler type is mismatched with URL parameters");
    static_assert(
        std::is_same<void,
                     decltype(f(
                         std::declval<crow::Request>(),
                         std::declval<std::shared_ptr<bmcweb::AsyncResp>&>(),
                         std::declval<Args>()...))>::value,
        "Handler function with response argument should have void "
        "return "
        "type");

    handler = std::forward<Func>(f);
  }

  template <typename Func>
  void operator()(std::string_view name, Func&& f) {
    nameStr = name;
    (*this).template operator()<Func>(std::forward(f));
  }

  template <typename Func>
  void replaceHandler(Func&& f) {
    this->operator()(f);
  }

  template <typename Func>
  void appendHandler(Func&& f) {
    this->operator()([f = std::forward<Func>(f), previousFunc = this->handler](
                         const crow::Request & req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         Args... args) {
      if (previousFunc) {
        previousFunc(req, asyncResp, args...);
      }
      std::function<void(crow::Response&)> previousCompleteFunc =
          asyncResp->res.releaseCompleteRequestHandler();
      auto strand = asyncResp->strand_;

      asyncResp->res.setCompleteRequestHandler(
          [req, previousCompleteFunc(std::move(previousCompleteFunc)), args...,
           f, strand, delegatedExpandLevel(asyncResp->delegatedExpandLevel)](
              crow::Response& resIn) mutable {
            std::shared_ptr<bmcweb::AsyncResp> newAsyncResp =
                std::make_shared<bmcweb::AsyncResp>(std::move(resIn), strand);

            // Pass delegatedExpandLevel so that hanlder in plugin can
            // handler efficient expand appending accordingly
            newAsyncResp->delegatedExpandLevel = delegatedExpandLevel;

            // previousCompleteFunc contains callback functions including
            // Redfish params and writing bytes to socket
            newAsyncResp->res.setCompleteRequestHandler(
                [previousCompleteFunc(std::move(previousCompleteFunc))](
                    crow::Response& resp) {
                  if (previousCompleteFunc) {
                    previousCompleteFunc(resp);
                  }
                });
            f(req, newAsyncResp, args...);
          });
    });
  }

  void handle(const Request& req,
              const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
              const RoutingParams& params) override {
    detail::routing_handler_call_helper::Call<
        detail::routing_handler_call_helper::CallParams<decltype(handler)>, 0,
        0, 0, 0, black_magic::S<Args...>, black_magic::S<>>()(
        detail::routing_handler_call_helper::CallParams<decltype(handler)>{
            handler, params, req, asyncResp});
  }

 private:
  std::function<void(const crow::Request&,
                     const std::shared_ptr<bmcweb::AsyncResp>&, Args...)>
      handler;  // NOLINT
};

class Trie {
 public:
  struct Node {
    unsigned ruleIndex{};  // NOLINT
    std::array<size_t, static_cast<size_t>(ParamType::MAX)>
        paramChildrens{};  // NOLINT
    using ChildMap = boost::container::flat_map<
        std::string, unsigned, std::less<>,
        std::vector<std::pair<std::string, unsigned>>>;
    ChildMap children;

    bool isSimpleNode() const {
      return ruleIndex == 0 &&
             std::all_of(std::begin(paramChildrens), std::end(paramChildrens),
                         [](size_t x) { return x == 0U; });
    }
  };

  Trie() : nodes(1) {}

 private:
  void optimizeNode(Node* node);

  void optimize() { optimizeNode(head()); }

 public:
  void validate() { optimize(); }

  void findRouteIndexes(const std::string& reqUrl,
                        std::vector<unsigned>& routeIndexes,
                        const Node* node = nullptr, unsigned pos = 0) const;

  std::pair<unsigned, RoutingParams> find(
      std::string_view reqUrl, const Node* node = nullptr, size_t pos = 0,
      RoutingParams* params = nullptr) const;

  void add(const std::string& url, unsigned ruleIndex);

 private:
  void debugNodePrint(Node* n, size_t level);

 public:
  void debugPrint() { debugNodePrint(head(), 0U); }

 private:
  const Node* head() const { return &nodes.front(); }

  Node* head() { return &nodes.front(); }

  unsigned newNode() {
    nodes.resize(nodes.size() + 1);
    return static_cast<unsigned>(nodes.size() - 1);
  }

  std::vector<Node> nodes;  // NOLINT
};

class Router {
 public:
  explicit Router(bool allowSessionEmpty)
      : allowSessionEmpty(allowSessionEmpty) {}

  DynamicRule& newRuleDynamic(const std::string& rule) {
    std::unique_ptr<DynamicRule> ruleObject =
        std::make_unique<DynamicRule>(rule);
    DynamicRule* ptr = ruleObject.get();
    allRules.emplace_back(std::move(ruleObject));

    return *ptr;
  }

  // Catch all rule is the rule used by default if no other rule is found.
  // This is used to unit testing easier so that we don't have to register every
  // individual route.
  template <uint64_t N>
  typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
  setCatchAllRule() {
    using RuleT =
        typename black_magic::Arguments<N>::type::template rebind<TaggedRule>;
    catch_all_rule_ = std::make_unique<RuleT>("*");
    RuleT* ptr = static_cast<RuleT*>(catch_all_rule_.get());
    return *ptr;
  }

  template <uint64_t N>
  typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
  newRuleTagged(std::string_view rule) {
    using RuleT =
        typename black_magic::Arguments<N>::type::template rebind<TaggedRule>;
    std::unique_ptr<RuleT> ruleObject = std::make_unique<RuleT>(rule);
    RuleT* ptr = ruleObject.get();
    allRules.emplace_back(std::move(ruleObject));

    return *ptr;
  }

  template <uint64_t Tag>
  void removeRuleTagged(std::string_view url,
                        boost::beast::http::verb boostVerb) {
    auto iter = findRuleByUrlAndVerb<Tag>(url, boostVerb);
    if (iter == allRules.end()) {
      throwHandlerNotFound(url, boostVerb);
    }
    allRules.erase(iter);
  }

  void internalAddRuleObject(const std::string& rule, BaseRule* ruleObject);

  void validate();

  struct FindRoute {
    BaseRule* rule = nullptr;
    RoutingParams params;
  };

  struct FindRouteResponse {
    std::string allowHeader;  // NOLINT
    FindRoute route;
  };

  FindRoute findRouteByIndex(std::string_view url, size_t index) const;

  FindRouteResponse findRoute(Request& req) const;

  template <typename CallbackFn>
  void afterGetUserInfo(Request& req,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        BaseRule& rule, CallbackFn&& callback,
                        const boost::system::error_code& ec,
                        const dbus::utility::DBusPropertiesMap& userInfoMap) {
    if (ec) {
      BMCWEB_LOG_ERROR << "GetUserInfo failed...";
      asyncResp->res.result(boost::beast::http::status::internal_server_error);
      return;
    }

    if (!isUserPrivileged(req, asyncResp, rule, userInfoMap)) {
      // User is not privileged
      BMCWEB_LOG_ERROR << "Insufficient Privilege";
      asyncResp->res.result(boost::beast::http::status::forbidden);
      return;
    }
    callback(req);
  }

  template <typename CallbackFn>
  void validatePrivilege(Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         BaseRule& rule, CallbackFn&& callback) {
    if (req.session == nullptr) {
      BMCWEB_LOG_DEBUG << "validatePrivilege: no session to validatePrivilege:";

      if (allowSessionEmpty) {
        callback(req);
      }

      return;
    }

    if (managedStore::GetManagedObjectStore()
                ->GetDeprecatedThreadUnsafeSystemBus() != nullptr &&
        req.session) {
      BMCWEB_LOG_DEBUG << "validatePrivilege: GetUserInfo";
      const std::string username = req.session->username;
      // TODO: WHY ARE WE DOING THIS FOR EVERY REQUEST ?!?! OMG. this is
      // absurd!
      managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
          asyncResp->strand_,
          [this, &req, asyncResp, &rule,
           callback(std::forward<CallbackFn>(callback))](
              const boost::system::error_code& ec,
              const dbus::utility::DBusPropertiesMap& userInfoMap) mutable {
            afterGetUserInfo(req, asyncResp, rule,
                             std::forward<CallbackFn>(callback), ec,
                             userInfoMap);
          },
          "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
          "xyz.openbmc_project.User.Manager", "GetUserInfo", username);
    } else {
      // systemBus = null is most likely unit testing
      callback(req);
    }
  }

  template <typename Adaptor>
  void handleUpgrade(Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     Adaptor&& adaptor) {
    std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
    if (!verb || static_cast<size_t>(*verb) >= perMethods.size()) {
      asyncResp->res.result(boost::beast::http::status::not_found);
      return;
    }
    PerMethod& perMethod = perMethods[static_cast<size_t>(*verb)];
    Trie& trie = perMethod.trie;
    std::vector<BaseRule*>& rules = perMethod.rules;

    const std::pair<unsigned, RoutingParams>& found =  // NOLINT
        trie.find(req.url().encoded_path());
    unsigned ruleIndex = found.first;
    if (ruleIndex == 0U) {
      BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url().encoded_path();
      asyncResp->res.result(boost::beast::http::status::not_found);
      return;
    }

    if (ruleIndex >= rules.size()) {
      throw std::runtime_error("Trie internal structure corrupted!");
    }

    BaseRule& rule = *rules[ruleIndex];
    size_t methods = rule.getMethods();
    if ((methods & (1U << static_cast<size_t>(*verb))) == 0) {
      BMCWEB_LOG_DEBUG << "Rule found but method mismatch: "
                       << req.url().encoded_path() << " with "
                       << req.methodString() << "("
                       << static_cast<uint32_t>(*verb) << ") / " << methods;
      asyncResp->res.result(boost::beast::http::status::not_found);
      return;
    }

    BMCWEB_LOG_DEBUG << "Matched rule (upgrade) '" << rule.rule << "' "
                     << static_cast<uint32_t>(*verb) << " / " << methods;

    // TODO(ed) This should be able to use std::bind_front, but it doesn't
    // appear to work with the std::move on adaptor.
    validatePrivilege(
        req, asyncResp, rule,
        [&rule, asyncResp,
         adaptor(std::forward<Adaptor>(adaptor))](Request& thisReq) mutable {
          rule.handleUpgrade(thisReq, asyncResp, std::move(adaptor));
        });
  }

  template <uint64_t Tag>
  std::vector<std::unique_ptr<BaseRule>>::iterator findRuleByUrlAndVerb(
      std::string_view url, boost::beast::http::verb boostVerb) {
    std::optional<HttpVerb> verb = httpVerbFromBoost(boostVerb);
    if (!verb) {
      return allRules.end();
    }

    for (auto iter = allRules.begin(); iter != allRules.end(); ++iter) {
      if ((*iter)->rule == url &&
          ((*iter)->methodsBitfield & (1 << static_cast<size_t>(*verb))) > 0) {
        return iter;
      }
    }
    return allRules.end();
  }

  void handle(Request& req,
              const std::shared_ptr<bmcweb::AsyncResp>& asyncResp);

  static bool isAccessAllowedFromInsecureTransport(const Request& req,
                                                   std::string_view url_str);

  static bool needsAuthorization(const Request& req, std::string_view url_str);

  void debugPrint();

  std::vector<const std::string*> getRoutes(const std::string& parent);

  static void throwHandlerNotFound(std::string_view url,
                                   boost::beast::http::verb boostVerb);

  template <uint64_t Tag, typename Func>
  void replaceHandler(std::string_view url, boost::beast::http::verb boostVerb,
                      Func&& func) {
    auto iter = findRuleByUrlAndVerb<Tag>(url, boostVerb);
    if (iter == allRules.end()) {
      throwHandlerNotFound(url, boostVerb);
    }
    using RuleT =
        black_magic::Arguments<Tag>::type::template rebind<TaggedRule>;
    RuleT* rule = dynamic_cast<RuleT*>(iter->get());
    rule->replaceHandler(func);
  }

  template <uint64_t Tag, typename Func>
  void appendHandler(std::string_view url, boost::beast::http::verb boostVerb,
                     Func&& func) {
    auto iter = findRuleByUrlAndVerb<Tag>(url, boostVerb);
    if (iter == allRules.end()) {
      throwHandlerNotFound(url, boostVerb);
    }
    using RuleT =
        typename black_magic::Arguments<Tag>::type::template rebind<TaggedRule>;
    RuleT* rule = dynamic_cast<RuleT*>(iter->get());

    rule->appendHandler(func);
  }

 private:
  static bool isUserPrivileged(
      Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      BaseRule& rule, const dbus::utility::DBusPropertiesMap& userInfoMap);

  struct PerMethod {
    std::vector<BaseRule*> rules;
    Trie trie;
    // rule index 0 has special meaning; preallocate it to avoid
    // duplication.
    PerMethod() : rules(1) {}
  };

  std::array<PerMethod, methodNotAllowedIndex + 1> perMethods;  // NOLINT
  std::vector<std::unique_ptr<BaseRule>> allRules;              // NOLINT
  std::unique_ptr<BaseRule> catch_all_rule_;
  bool allowSessionEmpty = false;  // NOLINT
};
}  // namespace crow

#endif  // THIRD_PARTY_GBMCWEB_HTTP_ROUTING_H_
