#ifndef seafire__server__hxx_
#define seafire__server__hxx_

#include <seafire/server/common-error.hxx>
#include <seafire/server/configuration.hxx>
#include <seafire/server/counter.hxx>
#include <seafire/server/request-handler.hxx>
#include <seafire/server/supervisor.hxx>

#include <seafire/common/diagnostics.hxx>

#include <seafire/common/io/acceptor.hxx>

namespace seafire::server
{

  class request_t;
  class response_t;
  class transaction_t;

  class server_t
    : public error_handler_t
  {
  public:
    /// Acceptor set type.
    ///
    using acceptor_set_t = std::set<std::unique_ptr<common::io::acceptor_t>>;

    server_t(common::diagnostics_t&,
             configuration_t,
             acceptor_set_t,
             request_handler_t);

    server_t(server_t const&) = delete;
    server_t(server_t&&) = delete;

    void
    start();

    void
    stop(bool = false);

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

  protected:
    void
    on_error(request_t&, response_t&, common_error_t) override;

    void
    on_exception(request_t&, response_t&) noexcept override;

    // fixme: void shutdown_stream();

  private:
    common::diagnostics_t::proxy_t
    trace();

    void
    init_accept(common::io::acceptor_t&);

    void
    on_accept(common::io::acceptor_t&, std::error_code const&);

    common::diagnostics_t& diagnostics_;
    configuration_t configuration_;
    acceptor_set_t const acceptors_;
    request_handler_t handler_;
    supervisor_t supervisor_;

  };

} // namespace seafire::server

#endif