#pragma once

#include "privileges.hpp"
#include "sessions.hpp"

#include <boost/container/flat_map.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/lexical_cast.hpp>
#include <cerrno>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <memory>
#include <tuple>
#include <utility>
#include <vector>

#include "crow/common.h"
#include "crow/http_request.h"
#include "crow/http_response.h"
#include "crow/logging.h"
#include "crow/utility.h"
#include "crow/websocket.h"

namespace crow
{

constexpr int maxHttpVerbCount =
    static_cast<int>(boost::beast::http::verb::unlink);

class BaseRule
{
  public:
    BaseRule(std::string thisRule) : rule(std::move(thisRule))
    {
    }

    virtual ~BaseRule()
    {
    }

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

    virtual void handle(const Request&, Response&, const RoutingParams&) = 0;
    virtual void handleUpgrade(const Request&, Response& res,
                               boost::asio::ip::tcp::socket&&)
    {
        res.result(boost::beast::http::status::not_found);
        res.end();
    }
#ifdef BMCWEB_ENABLE_SSL
    virtual void
        handleUpgrade(const Request&, Response& res,
                      boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&)
    {
        res.result(boost::beast::http::status::not_found);
        res.end();
    }
#endif

    uint32_t getMethods()
    {
        return methodsBitfield;
    }

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

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

    uint32_t methodsBitfield{1 << (int)boost::beast::http::verb::get};

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

    std::string rule;
    std::string nameStr;

    std::unique_ptr<BaseRule> ruleToUpgrade;

    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;
    Response& res;
};

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.res,
            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 = 0)
    {
        handler = [f = std::move(f)](const Request&, Response& res,
                                     Args... args) {
            res.result(f(args...));
            res.end();
        };
    }

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

        void operator()(const Request& req, Response& res, Args... args)
        {
            res.result(f(req, args...));
            res.end();
        }

        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,
                              Response&>::value,
            int>::type = 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,
                             Response&>::value,
            int>::type = 0)
    {
        handler = std::move(f);
    }

    template <typename... Args> struct HandlerTypeHelper
    {
        using type =
            std::function<void(const crow::Request&, crow::Response&, Args...)>;
        using args_type =
            black_magic::S<typename black_magic::promote_t<Args>...>;
    };

    template <typename... Args>
    struct HandlerTypeHelper<const Request&, Args...>
    {
        using type =
            std::function<void(const crow::Request&, crow::Response&, Args...)>;
        using args_type =
            black_magic::S<typename black_magic::promote_t<Args>...>;
    };

    template <typename... Args>
    struct HandlerTypeHelper<const Request&, Response&, Args...>
    {
        using type =
            std::function<void(const crow::Request&, crow::Response&, Args...)>;
        using args_type =
            black_magic::S<typename black_magic::promote_t<Args>...>;
    };

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

    void operator()(const Request& req, Response& res,
                    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, res});
    }
};
} // namespace routing_handler_call_helper
} // namespace detail

class WebSocketRule : public BaseRule
{
    using self_t = WebSocketRule;

  public:
    WebSocketRule(std::string rule) : BaseRule(std::move(rule))
    {
    }

    void validate() override
    {
    }

    void handle(const Request&, Response& res, const RoutingParams&) override
    {
        res.result(boost::beast::http::status::not_found);
        res.end();
    }

    void handleUpgrade(const Request& req, Response&,
                       boost::asio::ip::tcp::socket&& adaptor) override
    {
        new crow::websocket::ConnectionImpl<boost::asio::ip::tcp::socket>(
            req, std::move(adaptor), openHandler, messageHandler, closeHandler,
            errorHandler);
    }
#ifdef BMCWEB_ENABLE_SSL
    void handleUpgrade(const Request& req, Response&,
                       boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&
                           adaptor) override
    {
        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,
                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& 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;
    std::function<void(crow::websocket::Connection&, const std::string&, bool)>
        messageHandler;
    std::function<void(crow::websocket::Connection&, const std::string&)>
        closeHandler;
    std::function<void(crow::websocket::Connection&)> errorHandler;
};

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

    self_t& name(std::string name) noexcept
    {
        ((self_t*)this)->nameStr = std::move(name);
        return (self_t&)*this;
    }

    self_t& methods(boost::beast::http::verb method)
    {
        ((self_t*)this)->methodsBitfield = 1 << (int)method;
        return (self_t&)*this;
    }

    template <typename... MethodArgs>
    self_t& methods(boost::beast::http::verb method, MethodArgs... args_method)
    {
        methods(args_method...);
        ((self_t*)this)->methodsBitfield |= 1 << (int)method;
        return (self_t&)*this;
    }

    template <typename... MethodArgs>
    self_t& requires(std::initializer_list<const char*> l)
    {
        ((self_t*)this)->privilegesSet.emplace_back(l);
        return (self_t&)*this;
    }

    template <typename... MethodArgs>
    self_t& requires(const std::vector<redfish::Privileges>& p)
    {
        for (const redfish::Privileges& privilege : p)
        {
            ((self_t*)this)->privilegesSet.emplace_back(privilege);
        }
        return (self_t&)*this;
    }
};

class DynamicRule : public BaseRule, public RuleParameterTraits<DynamicRule>
{
  public:
    DynamicRule(std::string rule) : BaseRule(std::move(rule))
    {
    }

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

    void handle(const Request& req, Response& res,
                const RoutingParams& params) override
    {
        erasedHandler(req, res, params);
    }

    template <typename Func> void operator()(Func f)
    {
        using function_t = utility::function_traits<Func>;

        erasedHandler =
            wrap(std::move(f), black_magic::gen_seq<function_t::arity>());
    }

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

    template <typename Func, unsigned... Indices>

    std::function<void(const Request&, Response&, const RoutingParams&)>
        wrap(Func f, black_magic::Seq<Indices...>)
    {
        using function_t = utility::function_traits<Func>;

        if (!black_magic::isParameterTagCompatible(
                black_magic::getParameterTagRuntime(rule.c_str()),
                black_magic::compute_parameter_tag_from_args_list<
                    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&, Response&, const RoutingParams&)>
        erasedHandler;
};

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

    TaggedRule(std::string rule) : BaseRule(std::move(rule))
    {
    }

    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::resposne, nlohmann::json");

        handler = [f = std::move(f)](const Request&, Response& res,
                                     Args... args) {
            res.result(f(args...));
            res.end();
        };
    }

    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::resposne,nlohmann::json");

        handler = [f = std::move(f)](const crow::Request& req,
                                     crow::Response& res, Args... args) {
            res.result(f(req, args...));
            res.end();
        };
    }

    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, crow::Response&,
                                         Args...>>::value,
            "Handler type is mismatched with URL parameters");
        static_assert(
            std::is_same<void, decltype(f(std::declval<crow::Request>(),
                                          std::declval<crow::Response&>(),
                                          std::declval<Args>()...))>::value,
            "Handler function with response argument should have void "
            "return "
            "type");

        handler = std::move(f);
    }

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

    void handle(const Request& req, Response& res,
                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, res});
    }

  private:
    std::function<void(const crow::Request&, crow::Response&, Args...)> handler;
};

const int ruleSpecialRedirectSlash = 1;

class Trie
{
  public:
    struct Node
    {
        unsigned ruleIndex{};
        std::array<unsigned, (int)ParamType::MAX> paramChildrens{};
        boost::container::flat_map<std::string, unsigned> children;

        bool isSimpleNode() const
        {
            return !ruleIndex && std::all_of(std::begin(paramChildrens),
                                             std::end(paramChildrens),
                                             [](unsigned x) { return !x; });
        }
    };

    Trie() : nodes(1)
    {
    }

  private:
    void optimizeNode(Node* node)
    {
        for (unsigned int x : node->paramChildrens)
        {
            if (!x)
                continue;
            Node* child = &nodes[x];
            optimizeNode(child);
        }
        if (node->children.empty())
            return;
        bool mergeWithChild = true;
        for (const std::pair<std::string, unsigned>& kv : node->children)
        {
            Node* child = &nodes[kv.second];
            if (!child->isSimpleNode())
            {
                mergeWithChild = false;
                break;
            }
        }
        if (mergeWithChild)
        {
            decltype(node->children) merged;
            for (const std::pair<std::string, unsigned>& kv : node->children)
            {
                Node* child = &nodes[kv.second];
                for (const std::pair<std::string, unsigned>& childKv :
                     child->children)
                {
                    merged[kv.first + childKv.first] = childKv.second;
                }
            }
            node->children = std::move(merged);
            optimizeNode(node);
        }
        else
        {
            for (const std::pair<std::string, unsigned>& kv : node->children)
            {
                Node* child = &nodes[kv.second];
                optimizeNode(child);
            }
        }
    }

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

  public:
    void validate()
    {
        if (!head()->isSimpleNode())
            throw std::runtime_error(
                "Internal error: Trie header should be simple!");
        optimize();
    }

    void findRouteIndexes(const std::string& req_url,
                          std::vector<unsigned>& route_indexes,
                          const Node* node = nullptr, unsigned pos = 0) const
    {
        if (node == nullptr)
        {
            node = head();
        }
        for (const std::pair<std::string, unsigned>& kv : node->children)
        {
            const std::string& fragment = kv.first;
            const Node* child = &nodes[kv.second];
            if (pos >= req_url.size())
            {
                if (child->ruleIndex != 0 && fragment != "/")
                {
                    route_indexes.push_back(child->ruleIndex);
                }
                findRouteIndexes(req_url, route_indexes, child,
                                 pos + fragment.size());
            }
            else
            {
                if (req_url.compare(pos, fragment.size(), fragment) == 0)
                {
                    findRouteIndexes(req_url, route_indexes, child,
                                     pos + fragment.size());
                }
            }
        }
    }

    std::pair<unsigned, RoutingParams>
        find(const std::string_view req_url, const Node* node = nullptr,
             unsigned pos = 0, RoutingParams* params = nullptr) const
    {
        RoutingParams empty;
        if (params == nullptr)
            params = &empty;

        unsigned found{};
        RoutingParams matchParams;

        if (node == nullptr)
            node = head();
        if (pos == req_url.size())
            return {node->ruleIndex, *params};

        auto updateFound =
            [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) {
                if (ret.first && (!found || found > ret.first))
                {
                    found = ret.first;
                    matchParams = std::move(ret.second);
                }
            };

        if (node->paramChildrens[(int)ParamType::INT])
        {
            char c = req_url[pos];
            if ((c >= '0' && c <= '9') || c == '+' || c == '-')
            {
                char* eptr;
                errno = 0;
                long long int value =
                    std::strtoll(req_url.data() + pos, &eptr, 10);
                if (errno != ERANGE && eptr != req_url.data() + pos)
                {
                    params->intParams.push_back(value);
                    std::pair<unsigned, RoutingParams> ret =
                        find(req_url,
                             &nodes[node->paramChildrens[(int)ParamType::INT]],
                             eptr - req_url.data(), params);
                    updateFound(ret);
                    params->intParams.pop_back();
                }
            }
        }

        if (node->paramChildrens[(int)ParamType::UINT])
        {
            char c = req_url[pos];
            if ((c >= '0' && c <= '9') || c == '+')
            {
                char* eptr;
                errno = 0;
                unsigned long long int value =
                    std::strtoull(req_url.data() + pos, &eptr, 10);
                if (errno != ERANGE && eptr != req_url.data() + pos)
                {
                    params->uintParams.push_back(value);
                    std::pair<unsigned, RoutingParams> ret =
                        find(req_url,
                             &nodes[node->paramChildrens[(int)ParamType::UINT]],
                             eptr - req_url.data(), params);
                    updateFound(ret);
                    params->uintParams.pop_back();
                }
            }
        }

        if (node->paramChildrens[(int)ParamType::DOUBLE])
        {
            char c = req_url[pos];
            if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
            {
                char* eptr;
                errno = 0;
                double value = std::strtod(req_url.data() + pos, &eptr);
                if (errno != ERANGE && eptr != req_url.data() + pos)
                {
                    params->doubleParams.push_back(value);
                    std::pair<unsigned, RoutingParams> ret = find(
                        req_url,
                        &nodes[node->paramChildrens[(int)ParamType::DOUBLE]],
                        eptr - req_url.data(), params);
                    updateFound(ret);
                    params->doubleParams.pop_back();
                }
            }
        }

        if (node->paramChildrens[(int)ParamType::STRING])
        {
            size_t epos = pos;
            for (; epos < req_url.size(); epos++)
            {
                if (req_url[epos] == '/')
                    break;
            }

            if (epos != pos)
            {
                params->stringParams.emplace_back(
                    req_url.substr(pos, epos - pos));
                std::pair<unsigned, RoutingParams> ret =
                    find(req_url,
                         &nodes[node->paramChildrens[(int)ParamType::STRING]],
                         epos, params);
                updateFound(ret);
                params->stringParams.pop_back();
            }
        }

        if (node->paramChildrens[(int)ParamType::PATH])
        {
            size_t epos = req_url.size();

            if (epos != pos)
            {
                params->stringParams.emplace_back(
                    req_url.substr(pos, epos - pos));
                std::pair<unsigned, RoutingParams> ret = find(
                    req_url, &nodes[node->paramChildrens[(int)ParamType::PATH]],
                    epos, params);
                updateFound(ret);
                params->stringParams.pop_back();
            }
        }

        for (const std::pair<std::string, unsigned>& kv : node->children)
        {
            const std::string& fragment = kv.first;
            const Node* child = &nodes[kv.second];

            if (req_url.compare(pos, fragment.size(), fragment) == 0)
            {
                std::pair<unsigned, RoutingParams> ret =
                    find(req_url, child, pos + fragment.size(), params);
                updateFound(ret);
            }
        }

        return {found, matchParams};
    }

    void add(const std::string& url, unsigned ruleIndex)
    {
        unsigned idx{0};

        for (unsigned i = 0; i < url.size(); i++)
        {
            char c = url[i];
            if (c == '<')
            {
                const static std::array<std::pair<ParamType, std::string>, 7>
                    paramTraits = {{
                        {ParamType::INT, "<int>"},
                        {ParamType::UINT, "<uint>"},
                        {ParamType::DOUBLE, "<float>"},
                        {ParamType::DOUBLE, "<double>"},
                        {ParamType::STRING, "<str>"},
                        {ParamType::STRING, "<string>"},
                        {ParamType::PATH, "<path>"},
                    }};

                for (const std::pair<ParamType, std::string>& x : paramTraits)
                {
                    if (url.compare(i, x.second.size(), x.second) == 0)
                    {
                        if (!nodes[idx].paramChildrens[(int)x.first])
                        {
                            unsigned newNodeIdx = newNode();
                            nodes[idx].paramChildrens[(int)x.first] =
                                newNodeIdx;
                        }
                        idx = nodes[idx].paramChildrens[(int)x.first];
                        i += x.second.size();
                        break;
                    }
                }

                i--;
            }
            else
            {
                std::string piece(&c, 1);
                if (!nodes[idx].children.count(piece))
                {
                    unsigned newNodeIdx = newNode();
                    nodes[idx].children.emplace(piece, newNodeIdx);
                }
                idx = nodes[idx].children[piece];
            }
        }
        if (nodes[idx].ruleIndex)
            throw std::runtime_error("handler already exists for " + url);
        nodes[idx].ruleIndex = ruleIndex;
    }

  private:
    void debugNodePrint(Node* n, int level)
    {
        for (int i = 0; i < (int)ParamType::MAX; i++)
        {
            if (n->paramChildrens[i])
            {
                BMCWEB_LOG_DEBUG << std::string(
                    2 * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/;
                switch ((ParamType)i)
                {
                    case ParamType::INT:
                        BMCWEB_LOG_DEBUG << "<int>";
                        break;
                    case ParamType::UINT:
                        BMCWEB_LOG_DEBUG << "<uint>";
                        break;
                    case ParamType::DOUBLE:
                        BMCWEB_LOG_DEBUG << "<float>";
                        break;
                    case ParamType::STRING:
                        BMCWEB_LOG_DEBUG << "<str>";
                        break;
                    case ParamType::PATH:
                        BMCWEB_LOG_DEBUG << "<path>";
                        break;
                    default:
                        BMCWEB_LOG_DEBUG << "<ERROR>";
                        break;
                }

                debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
            }
        }
        for (const std::pair<std::string, unsigned>& kv : n->children)
        {
            BMCWEB_LOG_DEBUG
                << std::string(2 * level, ' ') /*<< "(" << kv.second << ") "*/
                << kv.first;
            debugNodePrint(&nodes[kv.second], level + 1);
        }
    }

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

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

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

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

    std::vector<Node> nodes;
};

class Router
{
  public:
    Router()
    {
    }

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

    template <uint64_t N>
    typename black_magic::Arguments<N>::type::template rebind<TaggedRule>&
        newRuleTagged(const std::string& 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;
    }

    void internalAddRuleObject(const std::string& rule, BaseRule* ruleObject)
    {
        if (ruleObject == nullptr)
        {
            return;
        }
        for (uint32_t method = 0, method_bit = 1; method < maxHttpVerbCount;
             method++, method_bit <<= 1)
        {
            if (ruleObject->methodsBitfield & method_bit)
            {
                perMethods[method].rules.emplace_back(ruleObject);
                perMethods[method].trie.add(
                    rule, perMethods[method].rules.size() - 1);
                // directory case:
                //   request to `/about' url matches `/about/' rule
                if (rule.size() > 2 && rule.back() == '/')
                {
                    perMethods[method].trie.add(
                        rule.substr(0, rule.size() - 1),
                        perMethods[method].rules.size() - 1);
                }
            }
        }
    }

    void validate()
    {
        for (std::unique_ptr<BaseRule>& rule : allRules)
        {
            if (rule)
            {
                std::unique_ptr<BaseRule> upgraded = rule->upgrade();
                if (upgraded)
                    rule = std::move(upgraded);
                rule->validate();
                internalAddRuleObject(rule->rule, rule.get());
            }
        }
        for (PerMethod& perMethod : perMethods)
        {
            perMethod.trie.validate();
        }
    }

    template <typename Adaptor>
    void handleUpgrade(const Request& req, Response& res, Adaptor&& adaptor)
    {
        if (static_cast<int>(req.method()) >= perMethods.size())
            return;

        PerMethod& perMethod = perMethods[(int)req.method()];
        Trie& trie = perMethod.trie;
        std::vector<BaseRule*>& rules = perMethod.rules;

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

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

        if (ruleIndex == ruleSpecialRedirectSlash)
        {
            BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
                            << req.url;
            res.result(boost::beast::http::status::moved_permanently);

            // TODO absolute url building
            if (req.getHeaderValue("Host").empty())
            {
                res.addHeader("Location", std::string(req.url) + "/");
            }
            else
            {
                res.addHeader(
                    "Location",
                    req.isSecure
                        ? "https://"
                        : "http://" + std::string(req.getHeaderValue("Host")) +
                              std::string(req.url) + "/");
            }
            res.end();
            return;
        }

        if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) ==
            0)
        {
            BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
                             << " with " << req.methodString() << "("
                             << (uint32_t)req.method() << ") / "
                             << rules[ruleIndex]->getMethods();
            res.result(boost::beast::http::status::not_found);
            res.end();
            return;
        }

        BMCWEB_LOG_DEBUG << "Matched rule (upgrade) '" << rules[ruleIndex]->rule
                         << "' " << (uint32_t)req.method() << " / "
                         << rules[ruleIndex]->getMethods();

        // any uncaught exceptions become 500s
        try
        {
            rules[ruleIndex]->handleUpgrade(req, res, std::move(adaptor));
        }
        catch (std::exception& e)
        {
            BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
            res.result(boost::beast::http::status::internal_server_error);
            res.end();
            return;
        }
        catch (...)
        {
            BMCWEB_LOG_ERROR
                << "An uncaught exception occurred. The type was unknown "
                   "so no information was available.";
            res.result(boost::beast::http::status::internal_server_error);
            res.end();
            return;
        }
    }

    void handle(const Request& req, Response& res)
    {
        if ((int)req.method() >= perMethods.size())
            return;
        PerMethod& perMethod = perMethods[(int)req.method()];
        Trie& trie = perMethod.trie;
        std::vector<BaseRule*>& rules = perMethod.rules;

        const std::pair<unsigned, RoutingParams>& found = trie.find(req.url);

        unsigned ruleIndex = found.first;

        if (!ruleIndex)
        {
            // Check to see if this url exists at any verb
            for (const PerMethod& p : perMethods)
            {
                const std::pair<unsigned, RoutingParams>& found =
                    p.trie.find(req.url);
                if (found.first > 0)
                {
                    res.result(boost::beast::http::status::method_not_allowed);
                    res.end();
                    return;
                }
            }
            BMCWEB_LOG_DEBUG << "Cannot match rules " << req.url;
            res.result(boost::beast::http::status::not_found);
            res.end();
            return;
        }

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

        if (ruleIndex == ruleSpecialRedirectSlash)
        {
            BMCWEB_LOG_INFO << "Redirecting to a url with trailing slash: "
                            << req.url;
            res.result(boost::beast::http::status::moved_permanently);

            // TODO absolute url building
            if (req.getHeaderValue("Host").empty())
            {
                res.addHeader("Location", std::string(req.url) + "/");
            }
            else
            {
                res.addHeader("Location",
                              (req.isSecure ? "https://" : "http://") +
                                  std::string(req.getHeaderValue("Host")) +
                                  std::string(req.url) + "/");
            }
            res.end();
            return;
        }

        if ((rules[ruleIndex]->getMethods() & (1 << (uint32_t)req.method())) ==
            0)
        {
            BMCWEB_LOG_DEBUG << "Rule found but method mismatch: " << req.url
                             << " with " << req.methodString() << "("
                             << (uint32_t)req.method() << ") / "
                             << rules[ruleIndex]->getMethods();
            res.result(boost::beast::http::status::method_not_allowed);
            res.end();
            return;
        }

        BMCWEB_LOG_DEBUG << "Matched rule '" << rules[ruleIndex]->rule << "' "
                         << (uint32_t)req.method() << " / "
                         << rules[ruleIndex]->getMethods();

        redfish::Privileges userPrivileges;
        if (req.session != nullptr)
        {
            // Get the user role from the session.
            const std::string& userRole = req.session->userRole;

            BMCWEB_LOG_DEBUG << "USER ROLE=" << userRole;

            // Get the user privileges from the role
            userPrivileges = redfish::getUserPrivileges(userRole);
        }

        if (!rules[ruleIndex]->checkPrivileges(userPrivileges))
        {
            res.result(boost::beast::http::status::forbidden);
            res.end();
            return;
        }

        // any uncaught exceptions become 500s
        try
        {
            rules[ruleIndex]->handle(req, res, found.second);
        }
        catch (std::exception& e)
        {
            BMCWEB_LOG_ERROR << "An uncaught exception occurred: " << e.what();
            res.result(boost::beast::http::status::internal_server_error);
            res.end();
            return;
        }
        catch (...)
        {
            BMCWEB_LOG_ERROR
                << "An uncaught exception occurred. The type was unknown "
                   "so no information was available.";
            res.result(boost::beast::http::status::internal_server_error);
            res.end();
            return;
        }
    }

    void debugPrint()
    {
        for (int i = 0; i < perMethods.size(); i++)
        {
            BMCWEB_LOG_DEBUG << methodName((boost::beast::http::verb)i);
            perMethods[i].trie.debugPrint();
        }
    }

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

        for (const PerMethod& pm : perMethods)
        {
            std::vector<unsigned> x;
            pm.trie.findRouteIndexes(parent, x);
            for (unsigned index : x)
            {
                ret.push_back(&pm.rules[index]->rule);
            }
        }
        return ret;
    }

  private:
    struct PerMethod
    {
        std::vector<BaseRule*> rules;
        Trie trie;
        // rule index 0, 1 has special meaning; preallocate it to avoid
        // duplication.
        PerMethod() : rules(2)
        {
        }
    };
    std::array<PerMethod, maxHttpVerbCount> perMethods;
    std::vector<std::unique_ptr<BaseRule>> allRules;
};
} // namespace crow
