// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once

#include "bmcweb_config.h"

#include "http_connect_types.hpp"
#include "http_connection.hpp"
#include "io_context_singleton.hpp"
#include "logging.hpp"
#include "ssl_key_handler.hpp"

#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/steady_timer.hpp>

#include <chrono>
#include <csignal>
#include <cstddef>
#include <ctime>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace crow
{

struct Acceptor
{
    boost::asio::ip::tcp::acceptor acceptor;
    HttpType httpType;
};

template <typename Handler, typename Adaptor = boost::asio::ip::tcp::socket>
class Server
{
    using self_t = Server<Handler, Adaptor>;

  public:
    Server(Handler* handlerIn, std::vector<Acceptor>&& acceptorsIn) :
        acceptors(std::move(acceptorsIn)),

        // NOLINTNEXTLINE(misc-include-cleaner)
        signals(getIoContext(), SIGINT, SIGTERM, SIGHUP), handler(handlerIn)
    {}

    void updateDateStr()
    {
        time_t lastTimeT = time(nullptr);
        tm myTm{};

        gmtime_r(&lastTimeT, &myTm);

        dateStr.resize(100);
        size_t dateStrSz = strftime(dateStr.data(), dateStr.size() - 1,
                                    "%a, %d %b %Y %H:%M:%S GMT", &myTm);
        dateStr.resize(dateStrSz);
    }

    void run()
    {
        loadCertificate();
        updateDateStr();

        getCachedDateStr = [this]() -> std::string {
            static std::chrono::time_point<std::chrono::steady_clock>
                lastDateUpdate = std::chrono::steady_clock::now();
            if (std::chrono::steady_clock::now() - lastDateUpdate >=
                std::chrono::seconds(10))
            {
                lastDateUpdate = std::chrono::steady_clock::now();
                updateDateStr();
            }
            return dateStr;
        };

        for (const Acceptor& accept : acceptors)
        {
            BMCWEB_LOG_INFO(
                "bmcweb server is running, local endpoint {}",
                accept.acceptor.local_endpoint().address().to_string());
        }
        startAsyncWaitForSignal();
        doAccept();
    }

    void loadCertificate()
    {
        if constexpr (BMCWEB_INSECURE_DISABLE_SSL)
        {
            return;
        }

        adaptorCtx = ensuressl::getSslServerContext();
    }

    void startAsyncWaitForSignal()
    {
        signals.async_wait(
            [this](const boost::system::error_code& ec, int signalNo) {
                if (ec)
                {
                    BMCWEB_LOG_INFO("Error in signal handler{}", ec.message());
                }
                else
                {
                    if (signalNo == SIGHUP)
                    {
                        BMCWEB_LOG_INFO("Receivied reload signal");
                        loadCertificate();
                        startAsyncWaitForSignal();
                    }
                    else
                    {
                        getIoContext().stop();
                    }
                }
            });
    }

    using SocketPtr = std::unique_ptr<Adaptor>;

    void afterAccept(SocketPtr socket, HttpType httpType,
                     const boost::system::error_code& ec)
    {
        if (ec)
        {
            BMCWEB_LOG_ERROR("Failed to accept socket {}", ec);
            return;
        }

        boost::asio::steady_timer timer(getIoContext());
        if (adaptorCtx == nullptr)
        {
            adaptorCtx = std::make_shared<boost::asio::ssl::context>(
                boost::asio::ssl::context::tls_server);
        }

        boost::asio::ssl::stream<Adaptor> stream(std::move(*socket),
                                                 *adaptorCtx);
        using ConnectionType = Connection<Adaptor, Handler>;
        auto connection = std::make_shared<ConnectionType>(
            handler, httpType, std::move(timer), getCachedDateStr,
            std::move(stream));

        boost::asio::post(getIoContext(),
                          [connection] { connection->start(); });

        doAccept();
    }

    void doAccept()
    {
        SocketPtr socket = std::make_unique<Adaptor>(getIoContext());
        // Keep a raw pointer so when the socket is moved, the pointer is still
        // valid
        Adaptor* socketPtr = socket.get();
        for (Acceptor& accept : acceptors)
        {
            accept.acceptor.async_accept(
                *socketPtr,
                std::bind_front(&self_t::afterAccept, this, std::move(socket),
                                accept.httpType));
        }
    }

  private:
    std::function<std::string()> getCachedDateStr;
    std::vector<Acceptor> acceptors;
    boost::asio::signal_set signals;

    std::string dateStr;

    Handler* handler;

    std::shared_ptr<boost::asio::ssl::context> adaptorCtx;
};
} // namespace crow
