#pragma once

#include "app_interface.h"
#include "async_resp.hpp"
#include "http_request.hpp"
#include "smart_router.h"
#include "utility.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#ifdef BMCWEB_ENABLE_SSL
#include <boost/asio/ssl/context.hpp>
#include <boost/beast/ssl/ssl_stream.hpp>
#endif

#include <array>
#include <chrono>
#include <cstdint>
#include <functional>
#include <future>
#include <memory>
#include <sstream>
#include <string>
#include <utility>

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define BMCWEB_ROUTE(app, url)                                                 \
    app.template route<crow::black_magic::getParameterTag(url)>(url)

#ifdef BMCWEB_ENABLE_SSL
using ssl_context_t = boost::asio::ssl::context;
using ssl_socket_t = boost::beast::ssl_stream<boost::asio::ip::tcp::socket>;
#else
using socket_t = boost::asio::ip::tcp::socket;
#endif

namespace crow
{

class App
{
  public:
    explicit App(bool allowSessionEmpty,
        std::shared_ptr<boost::asio::io_context> ioIn =
            std::make_shared<boost::asio::io_context>(),
            AppInterface* tlbmc_app = nullptr) :
        io(std::move(ioIn)),
        router(allowSessionEmpty, tlbmc_app)
    {}
    ~App()
    {
        this->stop();
    }

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

    template <typename Adaptor>
    void handleUpgrade(Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       Adaptor&& adaptor)
    {
        router.HandleUpgrade(req, asyncResp, std::forward<Adaptor>(adaptor));
    }

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

    DynamicRule& routeDynamic(std::string&& rule)
    {
        return router.NewRuleDynamic(std::move(rule));
    }

    template <uint64_t Tag>
    auto& route(std::string&& rule)
    {
        return router.NewRuleTagged<Tag>(std::move(rule));
    }

    App& socket(int existingSocket)
    {
        socketFd = existingSocket;
        return *this;
    }

    App& port(std::uint16_t port)
    {
        portUint = port;
        return *this;
    }

    App& bindaddr(std::string bindaddr)
    {
        bindaddrStr = std::move(bindaddr);
        return *this;
    }

    void validate()
    {
        router.Validate();
    }

    void run();

    void stop()
    {
        io->stop();
    }

    void debugPrint();

    std::vector<const std::string*> getRoutes()
    {
        const std::string root;
        return router.GetRoutes(root);
    }
    std::vector<const std::string*> getRoutes(const std::string& parent)
    {
        return router.GetRoutes(parent);
    }

    template <uint64_t Tag, typename Func, size_t N>
    void addHandler(std::string_view url, boost::beast::http::verb verb,
                    const std::array<redfish::Privileges, N>& p, Func&& func)
    {
        router.NewRuleTagged<Tag>(url).methods(verb).privileges(p)(func);
    }

    template <uint64_t Tag, typename Func>
    void replaceHandler(std::string_view url, boost::beast::http::verb verb,
                        Func&& func)
    {
        router.ReplaceHandler<Tag>(url, verb, func);
    }

    template <uint64_t Tag>
    void removeHandler(std::string_view url, boost::beast::http::verb verb)
    {
        router.RemoveHandler<Tag>(url, verb);
    }

    template <uint64_t Tag, typename Func>
    void appendHandler(std::string_view url, boost::beast::http::verb verb,
                       Func&& func)
    {
        router.AppendHandler<Tag>(url, verb, func);
    }

#ifdef BMCWEB_ENABLE_SSL
    App& ssl(std::shared_ptr<boost::asio::ssl::context>&& ctx)
    {
        sslContext = std::move(ctx);
        BMCWEB_LOG_INFO << "app::ssl context use_count="
                        << sslContext.use_count();
        return *this;
    }

    std::shared_ptr<ssl_context_t> sslContext = nullptr;

#else
    template <typename T>
    App& ssl(T&& /*unused*/)
    {
        // We can't call .ssl() member function unless BMCWEB_ENABLE_SSL is
        // defined.
        static_assert(
            // make static_assert dependent to T; always false
            std::is_base_of<T, void>::value,
            "Define BMCWEB_ENABLE_SSL to enable ssl support.");
        return *this;
    }
#endif

  private:
    std::shared_ptr<boost::asio::io_context> io;
#ifdef BMCWEB_ENABLE_SSL
    uint16_t portUint = 443;
#else
    uint16_t portUint = 80;
#endif
    std::string bindaddrStr = "0.0.0.0";
    int socketFd = -1;
    SmartRouter router;
};
} // namespace crow
using App = crow::App;
