#pragma once
#include <myapp/async/eventloop.h>
#include <myapp/async/pipe.h>
#include <myapp/async/signal.h>
#include <myapp/cmdargs/options.h>
#include <myapp/configuration/config.h>
#include <myapp/modbus/connection.h>
#include <myapp/modbus/device.h>
#include <myapp/persistence/database.h>
#include <myapp/rcon/server.h>
#include <memory>
#include <vector>

namespace myapp {

class daemon_facade final
{
public:
    explicit daemon_facade(cmdargs::options&, configuration::config&);

    void loop();

private:
    void set_console_termination_handlers();
    void open_remote_console();
    void open_local_console_if_nofork();
    void create_modbus_devices();
    void connect_modbus();
    void close_modbus();
    void open_database();
    std::string handle_command(std::string);

private:
    cmdargs::options& options_;
    configuration::config& config_;
    std::shared_ptr<logging::logger> logger_;
    std::shared_ptr<async::event_loop> loop_;
    std::unique_ptr<async::signal> sigint_;
    std::unique_ptr<async::signal> sigterm_;
    std::unique_ptr<async::pipe> stdin_;
    rcon::server rcon_;
    std::vector<std::shared_ptr<persistence::database>> databases_;
    std::vector<std::shared_ptr<modbus::connection>> modbus_connections_;
    std::vector<std::shared_ptr<modbus::device>> modbus_devices_;
    std::vector<std::function<void(std::string const&, std::string const&)>> subscribers_;
};

} /* namespace myapp */
